Skip to content

ResponseValidationError considered to be unsafe? #93

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

Closed
Nedgeva opened this issue Jan 4, 2020 · 5 comments · Fixed by #94
Closed

ResponseValidationError considered to be unsafe? #93

Nedgeva opened this issue Jan 4, 2020 · 5 comments · Fixed by #94

Comments

@Nedgeva
Copy link
Contributor

Nedgeva commented Jan 4, 2020

After getting some run-time exceptions in one app i took a closer look at ResponseValidationError implementation. Things that wonders me:

  1. why you're setting prototype of ResponseValidationError class to itself via setPrototypeOf? Isn't it's better to use Symbol.hasInstance for hooking instanceof?
  2. ResponseValidationError isn't safe because it's cannot be safely stringifed. Is this intended?

For example following code would produce run-time exceptions:

const failedValidation = pipe(
  fromEither(SomeCoded.decode(someInvalidData)),
  mapLeft<Errors, Error>(ResponseValidationError.create),
);
<RenderRemoteData data={failedValidation} ... />

where RenderRemoteData is something like

interface RenderRemoteDataProps<L, A> {
  data: RemoteData<L, A>;
  failure?: (e: L) => ReactNode;
  ...blah-blah-blah
}

const failureDefault = (e: Error) => (<div>{e.name}: {e.message}</div>);

const Component = <L, A>({
  data,
  failure = flow(toError, /* <-- downcasting ResponseValidationError to Error would cause exception like Uncaught TypeError: Function.prototype.toString requires that 'this' be a Function */ failureDefault),
}: RenderRemoteDataProps<L, A>) => {
  const error = useMemo(() => (e: L) => {
    console.warn('[RemoteDataFailure]', e);
    return failure(e);
  }, [failure]);

  return (
    {isFailure(data) && error(data.error)}
    <Blah />
  );
}

Would like to hear any thoughts on this.

Nedgeva added a commit to Nedgeva/swagger-codegen-ts that referenced this issue Jan 5, 2020
@raveclassic
Copy link
Contributor

why you're setting prototype of ResponseValidationError class to itself via setPrototypeOf?

Because we want instanceof Error to hold for instances of ResponseValidationError.

Isn't it's better to use Symbol.hasInstance for hooking instanceof?

Not sure why is it better? Could you clarify?

ResponseValidationError isn't safe because it's cannot be safely stringifed. Is this intended?

This is likely a bug. Do you mean that we also need to override Object.prototype.toString?

@Nedgeva
Copy link
Contributor Author

Nedgeva commented Jan 13, 2020

Because we want instanceof Error to hold for instances of ResponseValidationError.

Ok, but seems like it's breaks instanceof checking against parent class ResponseValidationError too.
Consider following code (nevermind light differencies):

class ResponseValidationError extends Error {
  static create(errors: string[]): ResponseValidationError {
    return new ResponseValidationError(errors);
  }

  constructor(readonly errors: string[]) {
    super(errors.join("\\n\\n"));
    this.name = "ResponseValidationError";
    Object.setPrototypeOf(this, ResponseValidationError);
  }
}

const responseValidationError = ResponseValidationError.create(['foo', 'bar']);
console.log(responseValidationError instanceof Error); // expected: false, got: false
console.log(responseValidationError instanceof ResponseValidationError); // expected: true, got: false

Not sure why is it better? Could you clarify?

At least this approach gives (i think) intentional behavior, when responseValidationError is instance only of parent class, not of Error or something.

This is likely a bug. Do you mean that we also need to override Object.prototype.toString?

Yep.

@raveclassic
Copy link
Contributor

but seems like it's breaks instanceof checking against parent class

That's seems like a bug too. We should use the following: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work

not of Error or something

But it's intentional! :)

@Nedgeva
Copy link
Contributor Author

Nedgeva commented Jan 13, 2020

Ok then)
If have some time please take a look on suggested solution in PR #94
It aims to fix incorrect instanceof behavior on ResponseValidationError and brings toString method.
Thanks!

@Nedgeva
Copy link
Contributor Author

Nedgeva commented Jan 14, 2020

But it's intentional! :)

Ouch, seems like i didn't got it at first time. So it was intended that instance of ResponseValidationError will match both ResponseValidationError and Error classes.
Reverted back some changes, only fixed Object.setPrototypeOf(this, ResponseValidationError) to Object.setPrototypeOf(this, ResponseValidationError.prototype).
(But i still think that hooking hasInstance better than manually change prototype chain 🤣 )

Nedgeva added a commit to Nedgeva/swagger-codegen-ts that referenced this issue Jul 29, 2020
fix: support windows os environment

fixed multiple errors that prevents from successful run on windows machine

feat: sketch file format

closes devexperts#76

refactor: relax specLikeCodec codec for sketch-121 schema

lint: remove unnecessary dependency

refactor: rename sketch parser to contain format version

refactor: fix opacity rendering

refactor: fix numeric rendering

chore: split document.ts to different files

chore: generate assets

docs: add a comment about a sketch-like structure

2.0.0-alpha.6

feat: implement support of kebab case in property names (devexperts#83)

closes devexperts#82

refactor: use Integer type from io-ts (devexperts#84)

BREAKING CHANGE: removed empty utils file

2.0.0-alpha.7

fix: fix encodeURIComponent in query serialization

2.0.0-alpha.8

fix: fix encodeURIComponent in query serialization

2.0.0-alpha.9

fix: fix '..' and '.' in spec names

BREAKING CHANGE: generate doesn't include `out` path in spec output
BREAKING CHANGE: language doesn't accept `out` path and can return `Fragment` to write to `out` directly

refactor: simplify resolveRef

BREAKING CHANGE: language is now a Reader of ResolveRefContext
BREAKING CHANGE: resolveRef now requires decoder as a second argument

chore: fix build

build: update prettier and eslint

style: update prettier and eslint

2.0.0-alpha.10

fix: revert join to resolve

feat: support cwd as `generate` argument

2.0.0-alpha.11

build: cleanup publishing artifact

build: cleanup publishing artifact

fix(sketch): avoid collision for names with counter

feat: support extract layers from sketch file

refactor: use traverseOptionEither

fix(sketch): add prefix to original layer name

2.0.0-alpha.12

fix: fix ResponseValidationError class in client

Fixes issue devexperts#93

fix: fix ResponseValidationError class in client

fix: fix ResponseValidationError class in client

refactor

fix: fix ResponseValidationError class to properly extend Error (devexperts#94)

closes devexperts#93

2.0.0-alpha.13

chore: update @devexeperts/* dependencies

2.0.0-alpha.14

feat: add `nullable` support for OpenAPI3

fix: fix OperationObject name generation without operationId

BREAKING CHANGE: if operation id is missing then url/pattern is included in the name

2.0.0-alpha.15

feat: expand sketch schema for support foreign symbols

feat: support date-time format (devexperts#100)

Added io-ts codec that supports date ignoring time

2.0.0-alpha.16

fix: add year padding to the codec (devexperts#101)

Added year padding to the codec to cover the case when backend returns  that should be treated as valid date

2.0.0-alpha.17

feat: filter operations response

BREAKING CHANGE: non-successful response types are filtered out of resulting response type

fix: incorrect generation "deprecated" jsdoc for method (devexperts#111)

fix: void response missing from union (devexperts#104) (devexperts#110)

BREAKING CHANGE: void response is added to resulting response type

fix: query string is incorrectly serialized for primitive parameters (devexperts#103) (devexperts#109)

build(deps): bump acorn from 5.7.3 to 5.7.4

Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](acornjs/acorn@5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <[email protected]>

2.0.0-alpha.18

feat: support arbitrary strings as type names in TS for OA3

closes devexperts#114

BREAKING CHANGE: type names and IO constant names now replace all non-alphanumeric characters with '_'

2.0.0-alpha.19

feat: support arbitrary names in path/query params

BREAKING CHANGE: query/path param names are now escaped

2.0.0-alpha.20

fix: change function name in utils file

2.0.0-alpha.21

fix(ts-utils): remove timezone detection from DateFromISODateStringIO, add tests

fix(ts-utils): refactor DateFromISODateStringIO

fix(ts-utils): rename vars in util

fix(ts-utils): remove tests

fix(ts-utils): remove export keyword
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