expo-modules-autolinking 55.0.21 → 55.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/build/platforms/devtools.js +11 -3
- package/build/platforms/devtools.js.map +1 -1
- package/build/utils.d.ts +1 -0
- package/build/utils.js +5 -0
- package/build/utils.js.map +1 -1
- package/package.json +2 -2
- package/scripts/ios/autolinking_manager.rb +7 -5
- package/scripts/ios/precompiled_modules.rb +91 -3
- package/src/platforms/devtools.ts +15 -3
- package/src/utils.ts +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 55.0.23 — 2026-05-19
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Disallow devtools plugins to point to `webpageRoot` outside of their own bounds ([#45841](https://github.com/expo/expo/pull/45841) by [@kitten](https://github.com/kitten))
|
|
18
|
+
|
|
19
|
+
## 55.0.22 — 2026-05-13
|
|
20
|
+
|
|
21
|
+
### 🐛 Bug fixes
|
|
22
|
+
|
|
23
|
+
[iOS] Added fallback to source for missing framework slice. ([#45664](https://github.com/expo/expo/pull/45664) by [@chrfalch](https://github.com/chrfalch))
|
|
24
|
+
|
|
13
25
|
## 55.0.21 — 2026-05-05
|
|
14
26
|
|
|
15
27
|
_This version does not introduce any user-facing changes._
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.resolveModuleAsync = resolveModuleAsync;
|
|
7
7
|
exports.resolveExtraBuildDependenciesAsync = resolveExtraBuildDependenciesAsync;
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const utils_1 = require("../utils");
|
|
9
10
|
async function resolveModuleAsync(packageName, revision) {
|
|
10
11
|
const devtoolsConfig = revision.config?.toJSON().devtools;
|
|
11
12
|
if (devtoolsConfig == null) {
|
|
@@ -14,12 +15,19 @@ async function resolveModuleAsync(packageName, revision) {
|
|
|
14
15
|
return {
|
|
15
16
|
packageName,
|
|
16
17
|
packageRoot: revision.path,
|
|
17
|
-
webpageRoot: devtoolsConfig.webpageRoot
|
|
18
|
-
? path_1.default.join(revision.path, devtoolsConfig.webpageRoot)
|
|
19
|
-
: undefined,
|
|
18
|
+
webpageRoot: await resolveWebpageRoot(revision.path, devtoolsConfig.webpageRoot),
|
|
20
19
|
cliExtensions: devtoolsConfig.cliExtensions,
|
|
21
20
|
};
|
|
22
21
|
}
|
|
22
|
+
async function resolveWebpageRoot(packageRoot, configuredWebpageRoot) {
|
|
23
|
+
if (!configuredWebpageRoot) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const resolvedWebpageRoot = path_1.default.resolve(packageRoot, configuredWebpageRoot);
|
|
27
|
+
// NOTE(@kitten): Failing realpath-ing, typically due to ENOENT, results in the original value
|
|
28
|
+
const webpageRoot = (await (0, utils_1.maybeRealpath)(resolvedWebpageRoot)) ?? resolvedWebpageRoot;
|
|
29
|
+
return (0, utils_1.isPathInside)(webpageRoot, packageRoot) ? webpageRoot : undefined;
|
|
30
|
+
}
|
|
23
31
|
async function resolveExtraBuildDependenciesAsync(_projectNativeRoot) {
|
|
24
32
|
return null;
|
|
25
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools.js","sourceRoot":"","sources":["../../src/platforms/devtools.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"devtools.js","sourceRoot":"","sources":["../../src/platforms/devtools.ts"],"names":[],"mappings":";;;;;AAKA,gDAeC;AAeD,gFAIC;AAvCD,gDAAwB;AAGxB,oCAAuD;AAEhD,KAAK,UAAU,kBAAkB,CACtC,WAAmB,EACnB,QAAyB;IAEzB,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC;IAC1D,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,WAAW;QACX,WAAW,EAAE,QAAQ,CAAC,IAAI;QAC1B,WAAW,EAAE,MAAM,kBAAkB,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,WAAW,CAAC;QAChF,aAAa,EAAE,cAAc,CAAC,aAAa;KAC5C,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,WAAmB,EACnB,qBAAyC;IAEzC,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,mBAAmB,GAAG,cAAI,CAAC,OAAO,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;IAC7E,8FAA8F;IAC9F,MAAM,WAAW,GAAG,CAAC,MAAM,IAAA,qBAAa,EAAC,mBAAmB,CAAC,CAAC,IAAI,mBAAmB,CAAC;IACtF,OAAO,IAAA,oBAAY,EAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1E,CAAC;AAEM,KAAK,UAAU,kCAAkC,CACtD,kBAA0B;IAE1B,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import path from 'path';\n\nimport type { ExtraDependencies, ModuleDescriptorDevTools, PackageRevision } from '../types';\nimport { isPathInside, maybeRealpath } from '../utils';\n\nexport async function resolveModuleAsync(\n packageName: string,\n revision: PackageRevision\n): Promise<ModuleDescriptorDevTools | null> {\n const devtoolsConfig = revision.config?.toJSON().devtools;\n if (devtoolsConfig == null) {\n return null;\n }\n\n return {\n packageName,\n packageRoot: revision.path,\n webpageRoot: await resolveWebpageRoot(revision.path, devtoolsConfig.webpageRoot),\n cliExtensions: devtoolsConfig.cliExtensions,\n };\n}\n\nasync function resolveWebpageRoot(\n packageRoot: string,\n configuredWebpageRoot: string | undefined\n): Promise<string | undefined> {\n if (!configuredWebpageRoot) {\n return undefined;\n }\n const resolvedWebpageRoot = path.resolve(packageRoot, configuredWebpageRoot);\n // NOTE(@kitten): Failing realpath-ing, typically due to ENOENT, results in the original value\n const webpageRoot = (await maybeRealpath(resolvedWebpageRoot)) ?? resolvedWebpageRoot;\n return isPathInside(webpageRoot, packageRoot) ? webpageRoot : undefined;\n}\n\nexport async function resolveExtraBuildDependenciesAsync(\n _projectNativeRoot: string\n): Promise<ExtraDependencies | null> {\n return null;\n}\n"]}
|
package/build/utils.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare function scanFilesRecursively(parentPath: string, includeDirector
|
|
|
11
11
|
export declare const fileExistsAsync: (file: string) => Promise<string | null>;
|
|
12
12
|
export declare const fastJoin: (from: string, append: string) => string;
|
|
13
13
|
export declare const maybeRealpath: (target: string) => Promise<string | null>;
|
|
14
|
+
export declare function isPathInside(child: string, parent: string): boolean;
|
|
14
15
|
export type PackageJson = Record<string, unknown> & {
|
|
15
16
|
name?: string;
|
|
16
17
|
version?: string;
|
package/build/utils.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.loadPackageJson = exports.maybeRealpath = exports.fastJoin = exports.fil
|
|
|
7
7
|
exports.listFilesSorted = listFilesSorted;
|
|
8
8
|
exports.listFilesInDirectories = listFilesInDirectories;
|
|
9
9
|
exports.scanFilesRecursively = scanFilesRecursively;
|
|
10
|
+
exports.isPathInside = isPathInside;
|
|
10
11
|
const fs_1 = __importDefault(require("fs"));
|
|
11
12
|
const path_1 = __importDefault(require("path"));
|
|
12
13
|
const memoize_1 = require("./memoize");
|
|
@@ -84,6 +85,10 @@ const maybeRealpath = async (target) => {
|
|
|
84
85
|
}
|
|
85
86
|
};
|
|
86
87
|
exports.maybeRealpath = maybeRealpath;
|
|
88
|
+
function isPathInside(child, parent) {
|
|
89
|
+
const relative = path_1.default.relative(parent, child);
|
|
90
|
+
return !!relative && !relative.startsWith('..') && !path_1.default.isAbsolute(relative);
|
|
91
|
+
}
|
|
87
92
|
exports.loadPackageJson = (0, memoize_1.memoize)(async function loadPackageJson(jsonPath) {
|
|
88
93
|
try {
|
|
89
94
|
const packageJsonText = await fs_1.default.promises.readFile(jsonPath, 'utf8');
|
package/build/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;AAMA,0CAaC;AAGD,wDAoBC;AAGD,oDA+BC;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { memoize } from './memoize';\n\n/** List filtered top-level files in `targetPath` (returns absolute paths) */\nexport async function listFilesSorted(\n targetPath: string,\n filter: (basename: string) => boolean\n): Promise<string[]> {\n try {\n // `readdir` isn't guaranteed to be sorted on Windows\n return (await fs.promises.readdir(targetPath, { withFileTypes: true }))\n .filter((entry) => entry.isFile() && filter(entry.name))\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((entry) => path.join(targetPath, entry.name));\n } catch {\n return [];\n }\n}\n\n/** List nested files in top-level directories in `targetPath` (returns relative paths) */\nexport async function listFilesInDirectories(\n targetPath: string,\n filter: (basename: string) => boolean\n): Promise<string[]> {\n return (\n await Promise.all(\n (await fs.promises.readdir(targetPath, { withFileTypes: true }))\n .filter((entry) => entry.isDirectory() && entry.name !== 'node_modules')\n .sort((a, b) => a.name.localeCompare(b.name))\n .map(async (directory) => {\n const entries = await fs.promises.readdir(path.join(targetPath, directory.name), {\n withFileTypes: true,\n });\n return entries\n .filter((entry) => entry.isFile() && filter(entry.name))\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((entry) => path.join(directory.name, entry.name));\n })\n )\n ).flat(1);\n}\n\n/** Iterate folders recursively for files, optionally sorting results and filtering directories */\nexport async function* scanFilesRecursively(\n parentPath: string,\n includeDirectory?: (parentPath: string, name: string) => boolean,\n sort = !fs.opendir\n) {\n const queue = [parentPath];\n let targetPath: string | undefined;\n while (queue.length > 0 && (targetPath = queue.shift()) != null) {\n try {\n const entries = sort\n ? (await fs.promises.readdir(targetPath, { withFileTypes: true })).sort((a, b) =>\n a.name.localeCompare(b.name)\n )\n : await fs.promises.opendir(targetPath);\n for await (const entry of entries) {\n if (entry.isDirectory() && entry.name !== 'node_modules') {\n if (!includeDirectory || includeDirectory(targetPath, entry.name)) {\n queue.push(path.join(targetPath, entry.name));\n }\n } else if (entry.isFile()) {\n yield {\n path: path.join(targetPath, entry.name),\n parentPath: targetPath,\n name: entry.name,\n } as const;\n }\n }\n } catch {\n continue;\n }\n }\n}\n\nexport const fileExistsAsync = async (file: string): Promise<string | null> => {\n const stat = await fs.promises.stat(file).catch(() => null);\n return stat?.isFile() ? file : null;\n};\n\nexport const fastJoin: (from: string, append: string) => string =\n path.sep === '/'\n ? (from, append) => `${from}${path.sep}${append}`\n : (from, append) =>\n `${from}${path.sep}${append[0] === '@' ? append.replace('/', path.sep) : append}`;\n\nexport const maybeRealpath = async (target: string): Promise<string | null> => {\n try {\n return await fs.promises.realpath(target);\n } catch {\n return null;\n }\n};\n\nexport function isPathInside(child: string, parent: string): boolean {\n const relative = path.relative(parent, child);\n return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);\n}\n\nexport type PackageJson = Record<string, unknown> & {\n name?: string;\n version?: string;\n peerDependencies?: Record<string, string>;\n codegenConfig?: Record<string, unknown>;\n};\n\nexport const loadPackageJson = memoize(async function loadPackageJson(\n jsonPath: string\n): Promise<PackageJson | null> {\n try {\n const packageJsonText = await fs.promises.readFile(jsonPath, 'utf8');\n const json = JSON.parse(packageJsonText);\n if (typeof json !== 'object' || json == null) {\n return null;\n }\n return json;\n } catch {\n return null;\n }\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-autolinking",
|
|
3
|
-
"version": "55.0.
|
|
3
|
+
"version": "55.0.23",
|
|
4
4
|
"description": "Scripts that autolink Expo modules.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"chalk": "^4.1.0",
|
|
44
44
|
"commander": "^7.2.0"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "fcb091766242d53248cd3c5949965961dbc5ec1d"
|
|
47
47
|
}
|
|
@@ -21,16 +21,18 @@ module Expo
|
|
|
21
21
|
|
|
22
22
|
validate_target_definition()
|
|
23
23
|
|
|
24
|
-
# Clear stale CocoaPods download cache for precompiled pods.
|
|
25
|
-
Expo::PrecompiledModules.clear_cocoapods_cache
|
|
26
|
-
|
|
27
24
|
resolve_result = resolve()
|
|
28
25
|
|
|
29
26
|
Expo::PackagesConfig.instance.coreFeatures = resolve_result['coreFeatures']
|
|
30
27
|
|
|
31
|
-
# Pass buildFromSource configuration to PrecompiledModules
|
|
32
28
|
configuration = resolve_result['configuration'] || {}
|
|
33
|
-
Expo::PrecompiledModules.
|
|
29
|
+
Expo::PrecompiledModules.configure(
|
|
30
|
+
target_platform: @target_definition.platform,
|
|
31
|
+
build_from_source: configuration['buildFromSource'] || []
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Clear stale CocoaPods download cache for precompiled pods.
|
|
35
|
+
Expo::PrecompiledModules.clear_cocoapods_cache
|
|
34
36
|
|
|
35
37
|
@packages = resolve_result['modules'].map { |json_package| Package.new(json_package) }
|
|
36
38
|
@extraPods = resolve_result['extraDependencies']
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
require 'fileutils'
|
|
30
30
|
require 'json'
|
|
31
31
|
require 'net/http'
|
|
32
|
+
require 'open3'
|
|
32
33
|
require 'set'
|
|
34
|
+
require 'tempfile'
|
|
33
35
|
require 'uri'
|
|
34
36
|
|
|
35
37
|
module Expo
|
|
@@ -76,6 +78,8 @@ module Expo
|
|
|
76
78
|
@framework_owner_map = nil # Hash: framework_name -> owning_pod_name
|
|
77
79
|
@failed_remote_downloads = Set.new
|
|
78
80
|
@warned_no_prebuilt_react = false
|
|
81
|
+
@target_platform = nil
|
|
82
|
+
@xcframework_slice_cache = nil
|
|
79
83
|
|
|
80
84
|
class << self
|
|
81
85
|
# Returns the build flavor (debug/release) for precompiled modules.
|
|
@@ -113,13 +117,26 @@ module Expo
|
|
|
113
117
|
false
|
|
114
118
|
end
|
|
115
119
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
def configure(target_platform: nil, build_from_source: nil)
|
|
121
|
+
self.target_platform = target_platform unless target_platform.nil?
|
|
122
|
+
self.build_from_source = build_from_source unless build_from_source.nil?
|
|
123
|
+
end
|
|
124
|
+
|
|
119
125
|
def build_from_source=(patterns)
|
|
120
126
|
@build_from_source_patterns = (patterns || []).map { |p| Regexp.new("^#{p}$") }
|
|
121
127
|
end
|
|
122
128
|
|
|
129
|
+
def target_platform=(platform)
|
|
130
|
+
normalized = normalize_xcframework_platform(platform)
|
|
131
|
+
return if @target_platform == normalized
|
|
132
|
+
|
|
133
|
+
@target_platform = normalized
|
|
134
|
+
@all_bundled_frameworks = nil
|
|
135
|
+
@claimed_vendored_frameworks = nil
|
|
136
|
+
@framework_owner_map = nil
|
|
137
|
+
@xcframework_slice_cache = nil
|
|
138
|
+
end
|
|
139
|
+
|
|
123
140
|
# Checks if a pod is configured to be built from source via buildFromSource.
|
|
124
141
|
# Matches against both the pod name and the npm package name.
|
|
125
142
|
def build_from_source?(pod_name)
|
|
@@ -1761,6 +1778,7 @@ module Expo
|
|
|
1761
1778
|
product_name = pod_info[:product_name] || pod_name
|
|
1762
1779
|
tarball = resolve_prebuilt_tarball(pod_info, product_name, build_flavor, pod_name)
|
|
1763
1780
|
return { available: false, reason: :missing_tarball, path: tarball } unless File.exist?(tarball)
|
|
1781
|
+
return { available: false, reason: :missing_platform_slice, path: tarball } unless xcframework_supports_target_platform?(tarball)
|
|
1764
1782
|
|
|
1765
1783
|
{ available: true, resolved: [pod_info, product_name, tarball] }
|
|
1766
1784
|
end
|
|
@@ -1818,6 +1836,74 @@ module Expo
|
|
|
1818
1836
|
remote_tarball
|
|
1819
1837
|
end
|
|
1820
1838
|
|
|
1839
|
+
def normalize_xcframework_platform(platform)
|
|
1840
|
+
name = platform.respond_to?(:name) ? platform.name : platform
|
|
1841
|
+
name = name.string_name if name.respond_to?(:string_name)
|
|
1842
|
+
normalized = name.to_s.downcase
|
|
1843
|
+
normalized == 'osx' ? 'macos' : normalized
|
|
1844
|
+
end
|
|
1845
|
+
|
|
1846
|
+
def xcframework_supports_target_platform?(path)
|
|
1847
|
+
return true unless @target_platform
|
|
1848
|
+
|
|
1849
|
+
@xcframework_slice_cache ||= {}
|
|
1850
|
+
cache_key = [path, @target_platform]
|
|
1851
|
+
return @xcframework_slice_cache[cache_key] if @xcframework_slice_cache.key?(cache_key)
|
|
1852
|
+
|
|
1853
|
+
@xcframework_slice_cache[cache_key] = begin
|
|
1854
|
+
info_plists = File.directory?(path) ? [read_plist(File.join(path, 'Info.plist'))] : read_xcframework_info_plists_from_tarball(path)
|
|
1855
|
+
info_plists.any? && info_plists.all? { |info_plist| info_plist_supports_target_platform?(info_plist) }
|
|
1856
|
+
end
|
|
1857
|
+
end
|
|
1858
|
+
|
|
1859
|
+
def info_plist_supports_target_platform?(info_plist)
|
|
1860
|
+
return false unless info_plist
|
|
1861
|
+
|
|
1862
|
+
available_libraries = info_plist['AvailableLibraries']
|
|
1863
|
+
return false unless available_libraries.is_a?(Array)
|
|
1864
|
+
|
|
1865
|
+
available_libraries.any? do |library|
|
|
1866
|
+
normalize_xcframework_platform(library['SupportedPlatform']) == @target_platform
|
|
1867
|
+
end
|
|
1868
|
+
end
|
|
1869
|
+
|
|
1870
|
+
def read_xcframework_info_plists_from_tarball(tarball)
|
|
1871
|
+
entries_output, status = Open3.capture2e('tar', 'tzf', tarball)
|
|
1872
|
+
unless status.success?
|
|
1873
|
+
Pod::UI.warn "[Expo-precompiled] Failed to inspect #{File.basename(tarball)}: #{entries_output.strip}"
|
|
1874
|
+
return []
|
|
1875
|
+
end
|
|
1876
|
+
|
|
1877
|
+
entries = entries_output.lines.map(&:strip)
|
|
1878
|
+
plist_entries = entries.select { |entry| entry.end_with?('.xcframework/Info.plist') }
|
|
1879
|
+
Pod::UI.warn "[Expo-precompiled] No XCFramework Info.plist found in #{File.basename(tarball)}" if plist_entries.empty?
|
|
1880
|
+
|
|
1881
|
+
plist_entries.filter_map do |entry|
|
|
1882
|
+
plist_data, plist_status = Open3.capture2e('tar', 'xOzf', tarball, entry)
|
|
1883
|
+
unless plist_status.success?
|
|
1884
|
+
Pod::UI.warn "[Expo-precompiled] Failed to extract #{entry} from #{File.basename(tarball)}: #{plist_data.strip}"
|
|
1885
|
+
next
|
|
1886
|
+
end
|
|
1887
|
+
|
|
1888
|
+
Tempfile.create(['expo-xcframework-info', '.plist']) do |file|
|
|
1889
|
+
file.binmode
|
|
1890
|
+
file.write(plist_data)
|
|
1891
|
+
file.flush
|
|
1892
|
+
read_plist(file.path)
|
|
1893
|
+
end
|
|
1894
|
+
end
|
|
1895
|
+
rescue StandardError => e
|
|
1896
|
+
Pod::UI.warn "[Expo-precompiled] Failed to inspect #{File.basename(tarball)}: #{e.message}"
|
|
1897
|
+
[]
|
|
1898
|
+
end
|
|
1899
|
+
|
|
1900
|
+
def read_plist(path)
|
|
1901
|
+
Xcodeproj::Plist.read_from_path(path)
|
|
1902
|
+
rescue StandardError => e
|
|
1903
|
+
Pod::UI.warn "[Expo-precompiled] Failed to read #{File.basename(path)}: #{e.message}"
|
|
1904
|
+
nil
|
|
1905
|
+
end
|
|
1906
|
+
|
|
1821
1907
|
def failed_remote_downloads
|
|
1822
1908
|
@failed_remote_downloads ||= Set.new
|
|
1823
1909
|
end
|
|
@@ -2096,6 +2182,8 @@ module Expo
|
|
|
2096
2182
|
'prebuilt config not found'
|
|
2097
2183
|
when :missing_tarball
|
|
2098
2184
|
'prebuilt tarball not found'
|
|
2185
|
+
when :missing_platform_slice
|
|
2186
|
+
"prebuilt xcframework does not contain a slice for #{@target_platform}"
|
|
2099
2187
|
when :dependency_unavailable
|
|
2100
2188
|
reason = format_prebuilt_unavailable_reason(reason: info[:dependency_reason], path: info[:dependency_path])
|
|
2101
2189
|
"dependency #{info[:dependency]} is not using prebuilt: #{reason}"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
|
|
3
3
|
import type { ExtraDependencies, ModuleDescriptorDevTools, PackageRevision } from '../types';
|
|
4
|
+
import { isPathInside, maybeRealpath } from '../utils';
|
|
4
5
|
|
|
5
6
|
export async function resolveModuleAsync(
|
|
6
7
|
packageName: string,
|
|
@@ -14,13 +15,24 @@ export async function resolveModuleAsync(
|
|
|
14
15
|
return {
|
|
15
16
|
packageName,
|
|
16
17
|
packageRoot: revision.path,
|
|
17
|
-
webpageRoot: devtoolsConfig.webpageRoot
|
|
18
|
-
? path.join(revision.path, devtoolsConfig.webpageRoot)
|
|
19
|
-
: undefined,
|
|
18
|
+
webpageRoot: await resolveWebpageRoot(revision.path, devtoolsConfig.webpageRoot),
|
|
20
19
|
cliExtensions: devtoolsConfig.cliExtensions,
|
|
21
20
|
};
|
|
22
21
|
}
|
|
23
22
|
|
|
23
|
+
async function resolveWebpageRoot(
|
|
24
|
+
packageRoot: string,
|
|
25
|
+
configuredWebpageRoot: string | undefined
|
|
26
|
+
): Promise<string | undefined> {
|
|
27
|
+
if (!configuredWebpageRoot) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const resolvedWebpageRoot = path.resolve(packageRoot, configuredWebpageRoot);
|
|
31
|
+
// NOTE(@kitten): Failing realpath-ing, typically due to ENOENT, results in the original value
|
|
32
|
+
const webpageRoot = (await maybeRealpath(resolvedWebpageRoot)) ?? resolvedWebpageRoot;
|
|
33
|
+
return isPathInside(webpageRoot, packageRoot) ? webpageRoot : undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
24
36
|
export async function resolveExtraBuildDependenciesAsync(
|
|
25
37
|
_projectNativeRoot: string
|
|
26
38
|
): Promise<ExtraDependencies | null> {
|
package/src/utils.ts
CHANGED
|
@@ -95,6 +95,11 @@ export const maybeRealpath = async (target: string): Promise<string | null> => {
|
|
|
95
95
|
}
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
+
export function isPathInside(child: string, parent: string): boolean {
|
|
99
|
+
const relative = path.relative(parent, child);
|
|
100
|
+
return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
101
|
+
}
|
|
102
|
+
|
|
98
103
|
export type PackageJson = Record<string, unknown> & {
|
|
99
104
|
name?: string;
|
|
100
105
|
version?: string;
|