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

Replace Uri.js with urijs npm module #9740

Merged
merged 17 commits into from
Sep 1, 2021
Merged

Replace Uri.js with urijs npm module #9740

merged 17 commits into from
Sep 1, 2021

Conversation

ebogo1
Copy link
Contributor

@ebogo1 ebogo1 commented Aug 20, 2021

This should not be merged until #9706 is in main.

Part of #9473. This code touches a lot of important files and there were a few things that came up; see my review comments.

@cesium-concierge
Copy link

Thanks for the pull request @ebogo1!

  • ✔️ Signed CLA found.
  • ❔ Changes to third party files were made.
    • Looks like a file in one of our ThirdParty folders (ThirdParty/, Source/ThirdParty/) has been added or modified. Please verify that it has a section in LICENSE.md and that its license information is up to date with this new version.

Reviewers, don't forget to make sure that:

  • Cesium Viewer works.
  • Works in 2D/CV.
  • Works (or fails gracefully) in IE11.

Copy link
Contributor Author

@ebogo1 ebogo1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, the urijs docs.


resource._url = uri.resolve(new Uri(getAbsoluteUri(this._url))).toString();
if (uri.is("urn")) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URI.absoluteTo() throws an exception when trying to concatenate URNs, whereas Uri.js returned the unchanged URN. Is this the correct behavior for Resource? There are a couple other places where this came up.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where exactly are the urn urls coming from?

Copy link
Contributor Author

@ebogo1 ebogo1 Aug 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible in .gltf and .czml files, i.e. the images in https://github.com/CesiumGS/cesium/blob/main/Specs/Data/Models/GltfLoader/BoxTextured/glTF-Embedded/BoxTextured.gltf, used in -

"./Data/Models/GltfLoader/BoxTextured/glTF-Embedded/BoxTextured.gltf";

Not sure how common this is, but it does happen in specs at the very least..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought data uris were different than urn?

According to https://stackoverflow.com/a/28865747 urn's start with urn:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there's definitely confusion here. almost everything is an urn.. so I'm not sure what differentiates from data uri or other in is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, I don't think just checking for data uris is enough - ModelOutlineLoaderSpec catches cases in Resource.getDerivedResource where the scheme is "blob". The third party Uri.js in main ignores the base URL's properties (including scheme) if the relative URL has them set:

if (this.scheme) {
uri.scheme = this.scheme;
uri.authority = this.authority;
uri.path = this.path;
uri.query = this.query;
} else {

Sandcastles and specs pass if everywhere that (incorrectly) checks Uri.is("urn") is changed to Uri.scheme() === "". This happens in RequestScheduler.getServerKey, Resource.getDerivedResource, and getAbsoluteUri. Is checking just for data schemes as opposed to checking for any scheme before calling Uri.absoluteTo preferable anywhere? Checking for any scheme at all is more faithful to the behavior in main.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what is the behavior for these urls in main? Do we just do nothing and return the original url? If so, then we can do the same thing here for now, but it could ultimately be masking a bug. Like should we be trying to absolutize or otherwise manipulate a opaque URL at all?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And wouldn't is("relative") be what we would want to check instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's basically the same check under the hood, but much clearer that we are only doing certain things for relative paths

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we just do nothing and return the original url?

Yes, this is what the current third party Uri.js does.

And wouldn't is("relative") be what we would want to check instead?

Not quite, since doing so falsely flags urls like "test.png", which causes spec failures. In main, new Uri("test.png").resolve(new Uri("http://localhost:8080/Specs/SpecRunner.html")) turns into "http://localhost:8080/Specs/test.png". This is consistent with this npm module's absoluteTo.

}
var url = relativeUri.absoluteTo(base).toString();
// URI.absoluteTo() escapes the placeholders. Undo that.
url = url.replace(/%7B/g, "{").replace(/%7D/g, "}");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was copied from Resource.prototype.getUrlComponent(); it's needed because the urijs implementation of absoluteTo normalizes URLs (this is also consistent with the URL(relative, base) constructor in JS. Is this logic safe here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We switched to absoluteTo in a unch of other places as well, why is this the only one that we needed this extra workaround for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a weird case that got caught by this line in specs -

getAbsoluteUri("made/up/tms/server/{z}/{x}/{reverseY}.jpg")

I don't think it's needed for any other reason..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It almost feels like this fix is in the wrong place, like the calling code is the thing that should be handling { or perhaps a specialized function like getAbsoluteTemplateStringUri.js Feels weird to just have something as generic as getAbsoluteUri embed code like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the string replace to the spec in question. Is there no risk of of this mattering at runtime because browsers treat encoded symbols the same as unencoded ones?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't realize the specs were the only place this happens.. did you verify any sandcastles using template uris for imager work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I verified that imagery Sandcastles work as expected, though there are bunch of Failed to obtain image tile X ... Y: ... Level: ... in the console.. this happens in the same way in main, doesn't seem like we have an open issue for it?

As far as I can tell only the spec calls getAbsoluteUri with a templated url - by the time the imagery urls make their way to fetchImage the template values are already string replaced correctly.


describe("Core/buildModuleUrl", function () {
it("produces an absolute URL for a module", function () {
var url = buildModuleUrl("Workers/transferTypedArrayTest.js");

expect(url).toMatch(/Workers\/transferTypedArrayTest.js$/);
expect(new Uri(url).isAbsolute()).toBe(true);
var uri = new URI(url);
expect(uri.scheme().length).toBeGreaterThan(0);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

urijs does not have an equivalent isAbsolute() function so I checked the scheme and fragment manually per the old Uri.js implementation. This change happens again in TaskProcessor.

Specs/DataSources/KmlDataSourceSpec.js Show resolved Hide resolved
@@ -521,8 +521,8 @@ function getDefaultCredit() {
logo.indexOf("https://") !== 0 &&
logo.indexOf("data:") !== 0
) {
var logoUrl = new Uri(logo);
logo = logoUrl.getPath();
var logoUrl = new URI(logo);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is never reached by specs..

@mramato
Copy link
Contributor

mramato commented Aug 22, 2021

Straight from their README

IMPORTANT: You may not need URI.js anymore! Modern browsers provide the URL and URLSearchParams interfaces.

What missing features are forcing us to use urljs (or any third party for that matter) instead of just using URL and URLSearchParams?

@mramato
Copy link
Contributor

mramato commented Aug 22, 2021

@ebogo1 you please merge in npm-third-party-staging (or main if that gets merged before you get to this)

@ebogo1
Copy link
Contributor Author

ebogo1 commented Aug 23, 2021

What missing features are forcing us to use urljs

@mramato URL expects a valid web URL and throws a type error for things like filepaths - URL docs.

@mramato
Copy link
Contributor

mramato commented Aug 23, 2021

@mramato URL expects a valid web URL and throws a type error for things like filepaths - URL docs.

I'm not sure what you mean. const url = new URL("file://users/mamato/test.gltf"); works fine.

Base automatically changed from npm-third-party-staging to main August 23, 2021 18:00
@ebogo1
Copy link
Contributor Author

ebogo1 commented Aug 23, 2021

@mramato TaskProcessor is one place that comes to mind; something like new URL("Workers/worker.js") will throw. Maybe less important but URL also does not have a normalize method..

Maybe it should be a follow-up to replace the npm module with stock URL?

@ebogo1 ebogo1 marked this pull request as ready for review August 23, 2021 20:07
@mramato
Copy link
Contributor

mramato commented Aug 24, 2021

TaskProcessor is one place that comes to mind; something like new URL("Workers/worker.js") will throw. M

That doesn't sound quite right.

Maybe less important but URL also does not have a normalize method..

MDN specifically mentioned you can just use the href property to normalize the URL.

All this being said, if this is a stop gap and we plan on taking a serious look into using stock URL post release, then I won't hold things up. It could also affect things like Node.js support. But in general it sounds like we assumed too much or gave up to early in trying to use the standard.

Specs/Core/ResourceSpec.js Outdated Show resolved Hide resolved
@ebogo1
Copy link
Contributor Author

ebogo1 commented Sep 1, 2021

Checking for any scheme at all is more faithful to the behavior in main.

Pushed a change in ca6a116 to replace is("urn") with scheme() !== "".

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 this pull request may close these issues.

4 participants