mirror of
https://github.com/apple/pkl.git
synced 2026-05-28 01:29:15 +02:00
Fix globbed read/import bugs (#449)
* Split MemberNode into (Regular/Shared)MemberNode SharedMemberNode enables generating non-constant object members at run time without generating an unbounded number of Truffle root nodes. * Invert shouldRunTypeCheck to match its name * Introduce VmObjectBuilder Introduce VmObjectBuilder, a uniform way to build `VmObject`s whose `ObjectMember`s are determined at run time. Replace some manual object building code with VmObjectBuilder. Add some assertions to fix IntelliJ warnings. * Improve implementation of globbed read/import nodes - Leverage SharedMemberNode to have a single Truffle root node per globbed read/import expression instead of one root node per resolved glob element. - Remove caching in ReadGlobNode because it only works correctly if glob pattern is a string *constant*. - Remove caching in StaticReadNode (now ReadGlobElementNode/ImportGlobElementNode) because it seems unnecessary and the implementation doesn't look quite right. * Simplify code * Fix ClassCastException when reflecting on globbed import * Fix caching of globbed reads Problem: The result of a globbed read depends not only on the glob pattern but also on the current module URI. However, ResourceManager does not take this into account when caching globbed reads, causing wrong results. Changes: - Cache globbed reads per read expression. This is also how globbed imports are cached, except that import URIs are constant. - Make ReadGlobNode and ImportGlobNode code as similar as possible. - Reduce code duplication by inheriting from AbstractReadNode. - Add some tests.
This commit is contained in:
+2
@@ -0,0 +1,2 @@
|
||||
normalRead = read("resource.txt")
|
||||
globbedRead = read*("*.txt")
|
||||
+1
@@ -0,0 +1 @@
|
||||
child resource
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
normalRead = read("resource.txt")
|
||||
globbedRead = read*("*.txt")
|
||||
+1
@@ -0,0 +1 @@
|
||||
resource
|
||||
@@ -22,14 +22,32 @@ examples {
|
||||
}
|
||||
|
||||
["read file"] {
|
||||
read("read.pkl")
|
||||
read("globtest/file1.txt")
|
||||
module.catch(() -> read("other.txt"))
|
||||
read?("read.pkl")
|
||||
read?("globtest/file1.txt")
|
||||
read?("other.txt")
|
||||
}
|
||||
|
||||
["read triple-dot file"] {
|
||||
read(".../input-helper/basic/read/resource.txt")
|
||||
read?(".../input-helper/basic/read/resource.txt")
|
||||
}
|
||||
|
||||
["read non-allowed resource"] {
|
||||
module.catch(() -> read("forbidden:resource"))
|
||||
module.catch(() -> read?("forbidden:resource"))
|
||||
}
|
||||
|
||||
["use read expression with non-constant resource URI"] {
|
||||
local function doRead(uri) = read(uri)
|
||||
doRead("globtest/file1.txt")
|
||||
doRead("globtest/file2.txt")
|
||||
}
|
||||
|
||||
["read different resources with same relative resource URI"] {
|
||||
local module1 = import(".../input-helper/basic/read/module1.pkl")
|
||||
local module2 = import(".../input-helper/basic/read/child/module2.pkl")
|
||||
module1.normalRead
|
||||
module2.normalRead
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,18 @@ examples {
|
||||
["package:"] {
|
||||
read*("package://localhost:0/birds@0.5.0#/**.pkl")
|
||||
}
|
||||
|
||||
["use read expression with non-constant glob pattern"] {
|
||||
local function doRead(pattern) = read*(pattern)
|
||||
doRead("globtest/file*.txt")
|
||||
doRead("globtest/file1.txt")
|
||||
doRead("globtest/file2.txt")
|
||||
}
|
||||
|
||||
["read different resources with same glob pattern"] {
|
||||
local module1 = import(".../input-helper/basic/read/module1.pkl")
|
||||
local module2 = import(".../input-helper/basic/read/child/module2.pkl")
|
||||
module1.globbedRead
|
||||
module2.globbedRead
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,94 +17,80 @@ examples {
|
||||
}
|
||||
["read file"] {
|
||||
new {
|
||||
uri = "file:///$snippetsDir/input/basic/read.pkl"
|
||||
uri = "file:///$snippetsDir/input/basic/globtest/file1.txt"
|
||||
text = """
|
||||
amends "../snippetTest.pkl"
|
||||
|
||||
examples {
|
||||
["read env variable"] {
|
||||
read("env:NAME1")
|
||||
read("env:NAME2")
|
||||
module.catch(() -> read("env:OTHER"))
|
||||
|
||||
read?("env:NAME1")
|
||||
read?("env:NAME2")
|
||||
read?("env:OTHER")
|
||||
}
|
||||
|
||||
["read external property"] {
|
||||
read("prop:name1")
|
||||
read("prop:name2")
|
||||
module.catch(() -> read("prop:other"))
|
||||
|
||||
read?("prop:name1")
|
||||
read?("prop:name2")
|
||||
read?("prop:other")
|
||||
}
|
||||
|
||||
["read file"] {
|
||||
read("read.pkl")
|
||||
module.catch(() -> read("other.txt"))
|
||||
read?("read.pkl")
|
||||
read?("other.txt")
|
||||
}
|
||||
|
||||
["read non-allowed resource"] {
|
||||
module.catch(() -> read("forbidden:resource"))
|
||||
module.catch(() -> read?("forbidden:resource"))
|
||||
}
|
||||
}
|
||||
file1
|
||||
|
||||
"""
|
||||
base64 = "YW1lbmRzICIuLi9zbmlwcGV0VGVzdC5wa2wiCgpleGFtcGxlcyB7CiAgWyJyZWFkIGVudiB2YXJpYWJsZSJdIHsKICAgIHJlYWQoImVudjpOQU1FMSIpCiAgICByZWFkKCJlbnY6TkFNRTIiKQogICAgbW9kdWxlLmNhdGNoKCgpIC0+IHJlYWQoImVudjpPVEhFUiIpKQoKICAgIHJlYWQ/KCJlbnY6TkFNRTEiKQogICAgcmVhZD8oImVudjpOQU1FMiIpCiAgICByZWFkPygiZW52Ok9USEVSIikKICB9CgogIFsicmVhZCBleHRlcm5hbCBwcm9wZXJ0eSJdIHsKICAgIHJlYWQoInByb3A6bmFtZTEiKQogICAgcmVhZCgicHJvcDpuYW1lMiIpCiAgICBtb2R1bGUuY2F0Y2goKCkgLT4gcmVhZCgicHJvcDpvdGhlciIpKQoKICAgIHJlYWQ/KCJwcm9wOm5hbWUxIikKICAgIHJlYWQ/KCJwcm9wOm5hbWUyIikKICAgIHJlYWQ/KCJwcm9wOm90aGVyIikKICB9CgogIFsicmVhZCBmaWxlIl0gewogICAgcmVhZCgicmVhZC5wa2wiKQogICAgbW9kdWxlLmNhdGNoKCgpIC0+IHJlYWQoIm90aGVyLnR4dCIpKQogICAgcmVhZD8oInJlYWQucGtsIikKICAgIHJlYWQ/KCJvdGhlci50eHQiKQogIH0KCiAgWyJyZWFkIG5vbi1hbGxvd2VkIHJlc291cmNlIl0gewogICAgbW9kdWxlLmNhdGNoKCgpIC0+IHJlYWQoImZvcmJpZGRlbjpyZXNvdXJjZSIpKQogICAgbW9kdWxlLmNhdGNoKCgpIC0+IHJlYWQ/KCJmb3JiaWRkZW46cmVzb3VyY2UiKSkKICB9Cn0K"
|
||||
base64 = "ZmlsZTEK"
|
||||
}
|
||||
"Cannot find resource `other.txt`."
|
||||
new {
|
||||
uri = "file:///$snippetsDir/input/basic/read.pkl"
|
||||
uri = "file:///$snippetsDir/input/basic/globtest/file1.txt"
|
||||
text = """
|
||||
amends "../snippetTest.pkl"
|
||||
|
||||
examples {
|
||||
["read env variable"] {
|
||||
read("env:NAME1")
|
||||
read("env:NAME2")
|
||||
module.catch(() -> read("env:OTHER"))
|
||||
|
||||
read?("env:NAME1")
|
||||
read?("env:NAME2")
|
||||
read?("env:OTHER")
|
||||
}
|
||||
|
||||
["read external property"] {
|
||||
read("prop:name1")
|
||||
read("prop:name2")
|
||||
module.catch(() -> read("prop:other"))
|
||||
|
||||
read?("prop:name1")
|
||||
read?("prop:name2")
|
||||
read?("prop:other")
|
||||
}
|
||||
|
||||
["read file"] {
|
||||
read("read.pkl")
|
||||
module.catch(() -> read("other.txt"))
|
||||
read?("read.pkl")
|
||||
read?("other.txt")
|
||||
}
|
||||
|
||||
["read non-allowed resource"] {
|
||||
module.catch(() -> read("forbidden:resource"))
|
||||
module.catch(() -> read?("forbidden:resource"))
|
||||
}
|
||||
}
|
||||
file1
|
||||
|
||||
"""
|
||||
base64 = "YW1lbmRzICIuLi9zbmlwcGV0VGVzdC5wa2wiCgpleGFtcGxlcyB7CiAgWyJyZWFkIGVudiB2YXJpYWJsZSJdIHsKICAgIHJlYWQoImVudjpOQU1FMSIpCiAgICByZWFkKCJlbnY6TkFNRTIiKQogICAgbW9kdWxlLmNhdGNoKCgpIC0+IHJlYWQoImVudjpPVEhFUiIpKQoKICAgIHJlYWQ/KCJlbnY6TkFNRTEiKQogICAgcmVhZD8oImVudjpOQU1FMiIpCiAgICByZWFkPygiZW52Ok9USEVSIikKICB9CgogIFsicmVhZCBleHRlcm5hbCBwcm9wZXJ0eSJdIHsKICAgIHJlYWQoInByb3A6bmFtZTEiKQogICAgcmVhZCgicHJvcDpuYW1lMiIpCiAgICBtb2R1bGUuY2F0Y2goKCkgLT4gcmVhZCgicHJvcDpvdGhlciIpKQoKICAgIHJlYWQ/KCJwcm9wOm5hbWUxIikKICAgIHJlYWQ/KCJwcm9wOm5hbWUyIikKICAgIHJlYWQ/KCJwcm9wOm90aGVyIikKICB9CgogIFsicmVhZCBmaWxlIl0gewogICAgcmVhZCgicmVhZC5wa2wiKQogICAgbW9kdWxlLmNhdGNoKCgpIC0+IHJlYWQoIm90aGVyLnR4dCIpKQogICAgcmVhZD8oInJlYWQucGtsIikKICAgIHJlYWQ/KCJvdGhlci50eHQiKQogIH0KCiAgWyJyZWFkIG5vbi1hbGxvd2VkIHJlc291cmNlIl0gewogICAgbW9kdWxlLmNhdGNoKCgpIC0+IHJlYWQoImZvcmJpZGRlbjpyZXNvdXJjZSIpKQogICAgbW9kdWxlLmNhdGNoKCgpIC0+IHJlYWQ/KCJmb3JiaWRkZW46cmVzb3VyY2UiKSkKICB9Cn0K"
|
||||
base64 = "ZmlsZTEK"
|
||||
}
|
||||
null
|
||||
}
|
||||
["read triple-dot file"] {
|
||||
new {
|
||||
uri = "file:///$snippetsDir/input-helper/basic/read/resource.txt"
|
||||
text = """
|
||||
resource
|
||||
|
||||
"""
|
||||
base64 = "cmVzb3VyY2UK"
|
||||
}
|
||||
new {
|
||||
uri = "file:///$snippetsDir/input-helper/basic/read/resource.txt"
|
||||
text = """
|
||||
resource
|
||||
|
||||
"""
|
||||
base64 = "cmVzb3VyY2UK"
|
||||
}
|
||||
}
|
||||
["read non-allowed resource"] {
|
||||
"Refusing to read resource `forbidden:resource` because it does not match any entry in the resource allowlist (`--allowed-resources`)."
|
||||
"Refusing to read resource `forbidden:resource` because it does not match any entry in the resource allowlist (`--allowed-resources`)."
|
||||
}
|
||||
["use read expression with non-constant resource URI"] {
|
||||
new {
|
||||
uri = "file:///$snippetsDir/input/basic/globtest/file1.txt"
|
||||
text = """
|
||||
file1
|
||||
|
||||
"""
|
||||
base64 = "ZmlsZTEK"
|
||||
}
|
||||
new {
|
||||
uri = "file:///$snippetsDir/input/basic/globtest/file2.txt"
|
||||
text = """
|
||||
file2
|
||||
|
||||
"""
|
||||
base64 = "ZmlsZTIK"
|
||||
}
|
||||
}
|
||||
["read different resources with same relative resource URI"] {
|
||||
new {
|
||||
uri = "file:///$snippetsDir/input-helper/basic/read/resource.txt"
|
||||
text = """
|
||||
resource
|
||||
|
||||
"""
|
||||
base64 = "cmVzb3VyY2UK"
|
||||
}
|
||||
new {
|
||||
uri = "file:///$snippetsDir/input-helper/basic/read/child/resource.txt"
|
||||
text = """
|
||||
child resource
|
||||
|
||||
"""
|
||||
base64 = "Y2hpbGQgcmVzb3VyY2UK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,4 +176,66 @@ examples {
|
||||
}
|
||||
}
|
||||
}
|
||||
["use read expression with non-constant glob pattern"] {
|
||||
new {
|
||||
["globtest/file1.txt"] {
|
||||
uri = "file:///$snippetsDir/input/basic/globtest/file1.txt"
|
||||
text = """
|
||||
file1
|
||||
|
||||
"""
|
||||
base64 = "ZmlsZTEK"
|
||||
}
|
||||
["globtest/file2.txt"] {
|
||||
uri = "file:///$snippetsDir/input/basic/globtest/file2.txt"
|
||||
text = """
|
||||
file2
|
||||
|
||||
"""
|
||||
base64 = "ZmlsZTIK"
|
||||
}
|
||||
}
|
||||
new {
|
||||
["globtest/file1.txt"] {
|
||||
uri = "file:///$snippetsDir/input/basic/globtest/file1.txt"
|
||||
text = """
|
||||
file1
|
||||
|
||||
"""
|
||||
base64 = "ZmlsZTEK"
|
||||
}
|
||||
}
|
||||
new {
|
||||
["globtest/file2.txt"] {
|
||||
uri = "file:///$snippetsDir/input/basic/globtest/file2.txt"
|
||||
text = """
|
||||
file2
|
||||
|
||||
"""
|
||||
base64 = "ZmlsZTIK"
|
||||
}
|
||||
}
|
||||
}
|
||||
["read different resources with same glob pattern"] {
|
||||
new {
|
||||
["resource.txt"] {
|
||||
uri = "file:///$snippetsDir/input-helper/basic/read/resource.txt"
|
||||
text = """
|
||||
resource
|
||||
|
||||
"""
|
||||
base64 = "cmVzb3VyY2UK"
|
||||
}
|
||||
}
|
||||
new {
|
||||
["resource.txt"] {
|
||||
uri = "file:///$snippetsDir/input-helper/basic/read/child/resource.txt"
|
||||
text = """
|
||||
child resource
|
||||
|
||||
"""
|
||||
base64 = "Y2hpbGQgcmVzb3VyY2UK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user