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

Fix exception on older browsers #246

Merged
merged 9 commits into from
Jun 19, 2024

Conversation

justinbhopper
Copy link
Contributor

Initial checklist

  • I read the support docs
  • I read the contributing guide
  • I agree to follow the code of conduct
  • I searched issues and couldn’t find anything (or linked relevant results below)
  • If applicable, I’ve added docs and tests

Description of changes

This addresses errors caused by the unified constructor in ES5 and fixes #245.

@github-actions github-actions bot added 👋 phase/new Post is being triaged automatically 🤞 phase/open Post is being triaged manually and removed 👋 phase/new Post is being triaged automatically labels Jun 5, 2024
@wooorm
Copy link
Member

wooorm commented Jun 6, 2024

Can you add a test?

@justinbhopper
Copy link
Contributor Author

Can you add a test?

Sure thing -- I've added tests specifically for CallableInstance that should cover this.

@codecov-commenter
Copy link

codecov-commenter commented Jun 6, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (b69689b) to head (dbc4e74).
Report is 5 commits behind head on main.

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #246   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3         3           
  Lines         1364      1372    +8     
=========================================
+ Hits          1364      1372    +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@justinbhopper
Copy link
Contributor Author

@wooorm I added some tests, please let me know if this looks good to you

package.json Outdated Show resolved Hide resolved
test/callable-instance.js Outdated Show resolved Hide resolved
@wooorm
Copy link
Member

wooorm commented Jun 17, 2024

Hi again, thanks for your patience!

As mentioned, we don’t support ES5, so it feels weird to include a test for ES5 support.

You said that this problem also occurs more broadly. I wonder if that is the case. Can you come up with a test that shows that to be the case?

In unified itself, we don’t use CallableInstance on just any value: we only use it on our own Processor class, our copy function. Adding a console.log('descriptor:', [p, descriptor?.value]) to the code and running the tests, I get:

descriptor: [ 'length', 0 ]
descriptor: [ 'name', 'copy' ]
descriptor: [ 'length', 0 ]
descriptor: [ 'name', 'copy' ]
descriptor: [ 'length', 0 ]
descriptor: [ 'name', 'copy' ]
descriptor: [ 'length', 0 ]
descriptor: [ 'name', 'copy' ]
descriptor: [ 'length', 0 ]
descriptor: [ 'name', 'copy' ]
descriptor: [ 'length', 0 ]
descriptor: [ 'name', 'copy' ]
...

Perhaps still your change would make sense to callable-instance (and first patched here), but then I worry that by omitting non-configurable fields makes your current exception disappear, but will result in more exceptions, because now the fields are omitted.

Or if that isn’t the case, perhaps that we don’t need this descriptor patching loop here at all?

Finally: adding your tests but not including your patch to lib, the tests still run for me?

@justinbhopper
Copy link
Contributor Author

@wooorm

As mentioned, we don’t support ES5, so it feels weird to include a test for ES5 support.

I added the tests per your request -- are you saying you want me to remove the tests now?

You said that this problem also occurs more broadly. I wonder if that is the case. Can you come up with a test that shows that to be the case?

Apologies, but I don't recall saying this. The problem only occurs when unified is used in a browser setting and is transpiled to ECMA 5.0. In fact, I can't even illustrate the bug in a test, because the issue only occurs on browsers and not in Node environment.

In unified itself, we don’t use CallableInstance on just any value: we only use it on our own Processor class, our copy function.

Yes, but the bug is specific to CallableInstance. The Processor class just happens to be the only class inheriting from it.

Perhaps still your change would make sense to callable-instance (and first patched here), but then I worry that by omitting non-configurable fields makes your current exception disappear, but will result in more exceptions, because now the fields are omitted.

I will make a change so we are instead checking the target object for an existing non-configurable property. This will ensure we're only skipping fields that are already defined and are non-configurable. This should ensure we're only skipping non-configurable properties that were defined on a brand new Function. It won't skip any non-configurable fields from the child class, so we won't be omitting anything from the class itself if they happen to define a non-configurable field.

Finally: adding your tests but not including your patch to lib, the tests still run for me?

That is because the tests run in Node, and Node does not define Functions with non-configurable properties like browsers do. I've only encountered this issue in a browser environment (Chrome). This sandbox illustrates the issue: https://playcode.io/1896334

@wooorm
Copy link
Member

wooorm commented Jun 18, 2024

I added the tests per your request -- are you saying you want me to remove the tests now?

No, I appreciate a test. But I was wondering if there could be a different test.

Apologies, but I don't recall saying this. The problem only occurs when unified is used in a browser setting and is transpiled to ECMA 5.0.

See #245 (comment)

In fact, I can't even illustrate the bug in a test, because the issue only occurs on browsers and not in Node environment.

Right, and this makes me wary: how can we be sure it’s fixed? That this fix does not introduce different problems?

and Node does not define Functions with non-configurable properties like browsers do.

You can still define non-configurable properties in the tests though?

This sandbox illustrates the issue: playcode.io/1896334

What is the illustration? What behavior do you expect, what not, what is actual? I don’t get errors in Chrome or Safari with that sandbox.

It won't skip any non-configurable fields from the child class, so we won't be omitting anything from the class itself if they happen to define a non-configurable field.

I worry about this approach: this approach attempts to patch callable-instance generically. So, this patch should be possible to upstream. However, this patch just drops some fields without warning. As there is no test, I worry that that would introduce more problems.

I can think of two alternative solutions.

a) Ignore this dead/unneeded code. All the tests should still run, so it’s verified.

-       const names = Object.getOwnPropertyNames(value)
-
-       for (const p of names) {
-         const descriptor = Object.getOwnPropertyDescriptor(value, p)
-         if (descriptor) Object.defineProperty(apply, p, descriptor)
-       }
+       // Not needed for us in `unified`: we only call this on the `copy`
+       // function,
+       // and we don’t need to add its fields (`length`, `name`)
+       // over.
+       // See also: GH-246.
+       // const names = Object.getOwnPropertyNames(value)
+       //
+       // for (const p of names) {
+       //   const descriptor = Object.getOwnPropertyDescriptor(value, p)
+       //   if (descriptor) Object.defineProperty(apply, p, descriptor)
+       // }

b) Create an exception for these legacy and unneeded fields:

        for (const p of names) {
+         // Special non-configurable legacy function fields (see: GH-246).
+         if (p === 'arguments' || p === 'caller') continue;
+
          const descriptor = Object.getOwnPropertyDescriptor(value, p)

(we could also probably add length here, which is available on non-Chrome, and also seems useless; then the branch is covered on Node too).

@justinbhopper
Copy link
Contributor Author

justinbhopper commented Jun 18, 2024

You can still define non-configurable properties in the tests though?

No, the bug is actually caused by attempts to redefine properties on the apply object, which is a fresh newly created Function:
image

There isn't any non-configurable fields that I can define that would cause this error. And now that we are checking the descriptor of the apply object's properties, the bug fix should be considered quite safe because it won't skip any non-configurable fields from the class/implementation.

What is the illustration? What behavior do you expect, what not, what is actual? I don’t get errors in Chrome or Safari with that sandbox.

Apologies, I accidentally saved the fix into the playground. If you look again using Chrome, you will see the original error.

image

I can think of two alternative solutions.

Your approach 'A' seems best to me. I didn't realize unified didn't actually need this cloning behavior. I agree, it seems unnecessary to attempt to clone properties of a function. Let me know if you would prefer I change the bug fix approach in this PR.

@wooorm
Copy link
Member

wooorm commented Jun 18, 2024

Thanks so much for thinking with me on this!

Let me know if you would prefer I change the bug fix approach in this PR.

Yes please!

I prefer approach A as well.
With that approach, I believe all the existing tests are enough, so the new tests can be removed.

@justinbhopper
Copy link
Contributor Author

@wooorm My pleasure! I've removed the tests and taken your suggested approach.

@wooorm wooorm changed the title Check configurable when defining property Fix exception on older browsers Jun 19, 2024
@wooorm wooorm merged commit 1e0863a into unifiedjs:main Jun 19, 2024
8 checks passed
@wooorm wooorm added 🐛 type/bug This is a problem 💪 phase/solved Post is done 🌐 platform/browser This affects browsers labels Jun 19, 2024

This comment has been minimized.

@github-actions github-actions bot removed the 🤞 phase/open Post is being triaged manually label Jun 19, 2024
@wooorm
Copy link
Member

wooorm commented Jun 19, 2024

released, thanks!

@justinbhopper justinbhopper deleted the callable-instance-fix branch June 19, 2024 14:14
renovate bot referenced this pull request in r4ai/r4ai.dev Jun 19, 2024
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [unified](https://unifiedjs.com)
([source](https://togithub.com/unifiedjs/unified)) | [`11.0.4` ->
`11.0.5`](https://renovatebot.com/diffs/npm/unified/11.0.4/11.0.5) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/unified/11.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/unified/11.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/unified/11.0.4/11.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/unified/11.0.4/11.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>unifiedjs/unified (unified)</summary>

###
[`v11.0.5`](https://togithub.com/unifiedjs/unified/releases/tag/11.0.5)

[Compare
Source](https://togithub.com/unifiedjs/unified/compare/11.0.4...11.0.5)

##### Fix

- [`1e0863a`](https://togithub.com/unifiedjs/unified/commit/1e0863a) Fix
exception on older browsers
by [@&#8203;justinbhopper](https://togithub.com/justinbhopper) in
[https://github.com/unifiedjs/unified/pull/246](https://togithub.com/unifiedjs/unified/pull/246)

**Full Changelog**:
unifiedjs/unified@11.0.4...11.0.5

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/r4ai/r4ai.dev).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MTAuMSIsInVwZGF0ZWRJblZlciI6IjM3LjQxMC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
kodiakhq bot referenced this pull request in X-oss-byte/Nextjs Jun 20, 2024
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [unified](https://unifiedjs.com) ([source](https://togithub.com/unifiedjs/unified)) | [`11.0.4` -> `11.0.5`](https://renovatebot.com/diffs/npm/unified/11.0.4/11.0.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/unified/11.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/unified/11.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/unified/11.0.4/11.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/unified/11.0.4/11.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>unifiedjs/unified (unified)</summary>

### [`v11.0.5`](https://togithub.com/unifiedjs/unified/releases/tag/11.0.5)

[Compare Source](https://togithub.com/unifiedjs/unified/compare/11.0.4...11.0.5)

##### Fix

-   [`1e0863a`](https://togithub.com/unifiedjs/unified/commit/1e0863a) Fix exception on older browsers
    by [@&#8203;justinbhopper](https://togithub.com/justinbhopper) in [https://github.com/unifiedjs/unified/pull/246](https://togithub.com/unifiedjs/unified/pull/246)

**Full Changelog**: unifiedjs/unified@11.0.4...11.0.5

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/X-oss-byte/Nextjs).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💪 phase/solved Post is done 🌐 platform/browser This affects browsers 🐛 type/bug This is a problem
Development

Successfully merging this pull request may close these issues.

CallableInstance throws error in older ECMA 5 targets
5 participants