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 JS library function fails stating object.clone is not a function #136

Closed
BaiqingL opened this issue May 26, 2024 · 6 comments · Fixed by #137
Closed

Calling JS library function fails stating object.clone is not a function #136

BaiqingL opened this issue May 26, 2024 · 6 comments · Fixed by #137

Comments

@BaiqingL
Copy link

BaiqingL commented May 26, 2024

I am trying to create a wrapper around the @smogon/calc library, and following its example essentially I am trying to re-implement this code-snippet with the python wrapper:

import {calculate, Generations, Pokemon, Move} from '@smogon/calc';

const gen = Generations.get(5); // alternatively: const gen = 5;
const result = calculate(
  gen,
  new Pokemon(gen, 'Gengar', {
    item: 'Choice Specs',
    nature: 'Timid',
    evs: {spa: 252},
    boosts: {spa: 1},
  }),
  new Pokemon(gen, 'Chansey', {
    item: 'Eviolite',
    nature: 'Calm',
    evs: {hp: 252, spd: 252},
  }),
  new Move(gen, 'Focus Blast')
);

Here is what I am doing in python

from javascript import require
damage_calc = require('@smogon/calc')
generation = damage_calc.Generations.get(5)
attacker = damage_calc.Pokemon(generation, 'Gengar', {
    'item': 'Choice Specs',
    'nature': 'Timid',
    'evs': {'spa': 252},
    'boosts': {'spa': 1},
  })
defender = damage_calc.Pokemon(generation, 'Chansey', {
    'item': 'Eviolite',
    'nature': 'Calm',
    'evs': {'hp': 252, 'spd': 252},
  })
move = damage_calc.Move(generation, 'Focus Blast')
damage = damage_calc.calculate(generation, attacker, defender, move)

Object creations works until I get to the damage line, the error states that

☕  JavaScript Error  Call to 'calculate' failed:
> damage = damage_calc.calculate(generation, attacker, defender, move)
  at <module> (/tmp/ipykernel_10306/2465370261.py:2)
> 

... across the bridge ...

  at Pipe.onStreamRead (node:internal/stream_base_commons:191:23)
  at Readable.push (node:internal/streams/readable:390:5)
  at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)
  at addChunk (node:internal/streams/readable:559:12)
  at Socket.emit (node:events:520:28)
  at Socket.<anonymous> (/home/andy/.conda/envs/dev/lib/python3.12/site-packages/javascript/js/bridge.js:292:18)
  at Bridge.onMessage (/home/andy/.conda/envs/dev/lib/python3.12/site-packages/javascript/js/bridge.js:231:25)
  at Bridge.call (/home/andy/.conda/envs/dev/lib/python3.12/site-packages/javascript/js/bridge.js:136:42)
  at Object.calculate (/home/andy/.conda/envs/dev/lib/python3.12/site-packages/javascript/js/node_modules/@smogon/calc/dist/index.js:46:39)
  at calculate (/home/andy/.conda/envs/dev/lib/python3.12/site-packages/javascript/js/node_modules/@smogon/calc/dist/calc.js:23:45)
> return MECHANICS[gen.num](gen, attacker.clone(), defender.clone(), move.clone(), field ? field.clone() : new field_1.Field());
🌉 TypeError: attacker.clone is not a function

It looks like the way I am creating the Pokemon object is wrong, as it doesn't seem to have the clone() function that it's supposed to. How am I supposed to create it properly?

@extremeheat
Copy link
Owner

Hi,

Your problem seems to be due to the Pokemon and Move objects not being proper ES6 classes (with class syntax), and are instead ES5 classes (standard functions with object extension behavior). This is usually due to bundlers/transpilers trying to support legacy JS engines that don't support JS features from 2015+. JSPyBridge will automatically call ES6 classes with new as it can detect them, but otherwise for old code you need to use the .new pseudo method to act similar to new <object> syntax in JS. This is mention under the "ES5 class" part of the readme doc.

There does seem to be a bug with .new handling, but it should be fixed with #137

@extremeheat
Copy link
Owner

Can you please checkout if

pip install https://github.com/extremeheat/JSPyBridge/archive/fix-es5-class.zip

fixes your issue?

Seems to work per
https://colab.research.google.com/gist/extremeheat/00c880b7d77fdc8dab90080e50e91c0f/jspybridge-136.ipynb

@BaiqingL
Copy link
Author

Hmm, upon running that install I seem to get this error:

☕  JavaScript Error  Call to '' failed:
> attacker = damage_calc.Pokemon.new(generation, 'Gengar', {
  at <module> (/home/andy/Documents/damage-calc-py-wrapper/run_print.py:5)
> 

... across the bridge ...

  at Pipe.onStreamRead (node:internal/stream_base_commons:191:23)
  at Readable.push (node:internal/streams/readable:390:5)
  at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)
  at addChunk (node:internal/streams/readable:559:12)
  at Socket.emit (node:events:520:28)
  at Socket.<anonymous> (/home/andy/.conda/envs/dev/lib/python3.12/site-packages/javascript/js/bridge.js:292:18)
  at Bridge.onMessage (/home/andy/.conda/envs/dev/lib/python3.12/site-packages/javascript/js/bridge.js:231:25)
  at Bridge.init (/home/andy/.conda/envs/dev/lib/python3.12/site-packages/javascript/js/bridge.js:128:68)
  TypeError: this.m[ffid] is not a constructor
> ^
🌉 TypeError: this.m[ffid] is not a constructor

@extremeheat
Copy link
Owner

You are probably not using the correct version of the package, that is what #137 is fixing, please test on the linked notebook any code you modified to ensure a clean environment. If you can reproduce please provide a colab or link to notebook.

@BaiqingL
Copy link
Author

I see, this works now, thanks.

@extremeheat
Copy link
Owner

Should be fixed in v1.2.1

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

Successfully merging a pull request may close this issue.

2 participants