diff --git a/src/3rdparty b/src/3rdparty index 4c7ecce30045daf172dceaeeb86351f60cc91990..5bbb0fff1e645bb29cd740767cda698e4e6d23e7 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 4c7ecce30045daf172dceaeeb86351f60cc91990 +Subproject commit 5bbb0fff1e645bb29cd740767cda698e4e6d23e7 diff --git a/tests/auto/widgets/origins/tst_origins.cpp b/tests/auto/widgets/origins/tst_origins.cpp index 59cbdae132eeda22149137dcec0559a4730a4fb2..21afead1de00f3190bfdfc4b6d61fd2cebb42a16 100644 --- a/tests/auto/widgets/origins/tst_origins.cpp +++ b/tests/auto/widgets/origins/tst_origins.cpp @@ -172,6 +172,7 @@ private Q_SLOTS: void cleanupTestCase(); void jsUrlCanon(); + void jsUrlRelative(); void jsUrlOrigin(); void subdirWithAccess(); void subdirWithoutAccess(); @@ -281,6 +282,54 @@ void tst_Origins::jsUrlCanon() QVariant(QSL("hostportanduserinformationsyntax://a:b@foo/bar"))); } +// Test relative URL resolution. +void tst_Origins::jsUrlRelative() +{ + QVERIFY(load(QSL("about:blank"))); + + // Schemes with hosts, like http, work as expected. + QCOMPARE(eval(QSL("new URL('bar', 'http://foo').href")), QVariant(QSL("http://foo/bar"))); + QCOMPARE(eval(QSL("new URL('baz', 'http://foo/bar').href")), QVariant(QSL("http://foo/baz"))); + QCOMPARE(eval(QSL("new URL('baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/bar/baz"))); + QCOMPARE(eval(QSL("new URL('/baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz"))); + QCOMPARE(eval(QSL("new URL('./baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/bar/baz"))); + QCOMPARE(eval(QSL("new URL('../baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz"))); + QCOMPARE(eval(QSL("new URL('../../baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz"))); + QCOMPARE(eval(QSL("new URL('//baz', 'http://foo/bar/').href")), QVariant(QSL("http://baz/"))); + + // In the case of schemes without hosts, relative URLs only work if the URL + // starts with a single slash -- and canonicalization does not guarantee + // this. The following cases all fail with TypeErrors. + QCOMPARE(eval(QSL("new URL('bar', 'tst:foo').href")), QVariant()); + QCOMPARE(eval(QSL("new URL('baz', 'tst:foo/bar').href")), QVariant()); + QCOMPARE(eval(QSL("new URL('bar', 'tst://foo').href")), QVariant()); + QCOMPARE(eval(QSL("new URL('bar', 'tst:///foo').href")), QVariant()); + + // However, registered custom schemes have been patched to allow relative + // URLs even without an initial slash. + QCOMPARE(eval(QSL("new URL('bar', 'qrc:foo').href")), QVariant(QSL("qrc:bar"))); + QCOMPARE(eval(QSL("new URL('baz', 'qrc:foo/bar').href")), QVariant(QSL("qrc:foo/baz"))); + QCOMPARE(eval(QSL("new URL('bar', 'qrc://foo').href")), QVariant()); + QCOMPARE(eval(QSL("new URL('bar', 'qrc:///foo').href")), QVariant()); + + // With a slash it works the same as http except 'foo' is part of the path and not the host. + QCOMPARE(eval(QSL("new URL('bar', 'qrc:/foo').href")), QVariant(QSL("qrc:/bar"))); + QCOMPARE(eval(QSL("new URL('bar', 'qrc:/foo/').href")), QVariant(QSL("qrc:/foo/bar"))); + QCOMPARE(eval(QSL("new URL('baz', 'qrc:/foo/bar').href")), QVariant(QSL("qrc:/foo/baz"))); + QCOMPARE(eval(QSL("new URL('baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/bar/baz"))); + QCOMPARE(eval(QSL("new URL('/baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz"))); + QCOMPARE(eval(QSL("new URL('./baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/bar/baz"))); + QCOMPARE(eval(QSL("new URL('../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/baz"))); + QCOMPARE(eval(QSL("new URL('../../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz"))); + QCOMPARE(eval(QSL("new URL('../../../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz"))); + + // If the relative URL begins with >= 2 slashes, then the scheme is treated + // not as a Syntax::Path scheme but as a Syntax::HostPortAndUserInformation + // scheme. + QCOMPARE(eval(QSL("new URL('//baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc://baz/"))); + QCOMPARE(eval(QSL("new URL('///baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc://baz/"))); +} + // Test origin serialization in Blink, implemented by blink::KURL and // blink::SecurityOrigin as opposed to GURL and url::Origin. void tst_Origins::jsUrlOrigin()