Skip to content

Large diffs are not rendered by default.

39 changes: 32 additions & 7 deletions packages/js/core-client/src/PolywrapCoreClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
WrapManifest,
} from "@polywrap/wrap-manifest-types-js";
import { Result, ResultErr, ResultOk } from "@polywrap/result";
import { UriResolutionResult } from "@polywrap/uri-resolvers-js";

export class PolywrapCoreClient implements CoreClient {
// $start: PolywrapCoreClient-constructor
Expand Down Expand Up @@ -274,29 +275,53 @@ export class PolywrapCoreClient implements CoreClient {
const resolutionContext =
options.resolutionContext ?? new UriResolutionContext();

const loadWrapperContext = resolutionContext.createSubContext();

const loadWrapperResult = await this.loadWrapper(
typedOptions.uri,
resolutionContext
loadWrapperContext
);

resolutionContext.trackStep({
sourceUri: typedOptions.uri,
result: loadWrapperResult.ok
? UriResolutionResult.ok(typedOptions.uri, loadWrapperResult.value)
: UriResolutionResult.err(loadWrapperResult.error),
description: `Client.loadWrapper(${typedOptions.uri.uri})`,
subHistory: loadWrapperContext.getHistory(),
});

if (!loadWrapperResult.ok) {
return loadWrapperResult;
}
const wrapper = loadWrapperResult.value;

const resolutionPath = resolutionContext.getResolutionPath();
let resolutionPath = loadWrapperContext.getResolutionPath();
resolutionPath =
resolutionPath.length > 0 ? resolutionPath : [typedOptions.uri];

const env = getEnvFromUriHistory(
resolutionPath.length > 0 ? resolutionPath : [typedOptions.uri],
this
);
const env = getEnvFromUriHistory(resolutionPath, this);

const invokeContext = resolutionContext.createSubContext();

const invokeResult = await this.invokeWrapper<TData>({
env: env,
...typedOptions,
env: env,
resolutionContext: invokeContext,
wrapper,
});

const finalUri = resolutionPath[resolutionPath.length - 1];

resolutionContext.trackStep({
sourceUri: finalUri,
result: invokeResult.ok
? UriResolutionResult.ok(finalUri)
: ResultErr(invokeResult.error),
description: `Client.invoke(${finalUri.uri})`,
subHistory: invokeContext.getHistory(),
});

if (!invokeResult.ok) {
return invokeResult;
}
Expand Down
22 changes: 20 additions & 2 deletions packages/js/core/src/types/CoreClient.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Invoker, Uri, WrapError, WrapperEnv } from ".";
import { Invoker, Uri, WrapError, Wrapper, WrapperEnv } from ".";
import { IUriResolutionContext, IUriResolver } from "../uri-resolution";
import { UriResolverHandler } from "./UriResolver";
import { ReadonlyUriMap } from "./UriMap";

import { WrapManifest } from "@polywrap/wrap-manifest-types-js";
import {
DeserializeManifestOptions,
WrapManifest,
} from "@polywrap/wrap-manifest-types-js";
import { Result } from "@polywrap/result";

// $start: CoreClient.ts
Expand Down Expand Up @@ -117,6 +120,21 @@ export interface CoreClient extends Invoker, UriResolverHandler<unknown> {
uri: Uri,
options: GetImplementationsOptions
): Promise<Result<Uri[], WrapError>>;

/**
* Resolve a URI to a wrap package or wrapper.
* If the URI resolves to wrap package, load the wrapper.
*
* @param uri - the Uri to resolve
* @param resolutionContext? - a resolution context
* @param options - { noValidate?: boolean }
* @returns A Promise with a Result containing a Wrapper or Error
*/
loadWrapper(
uri: Uri,
resolutionContext?: IUriResolutionContext,
options?: DeserializeManifestOptions
): Promise<Result<Wrapper, WrapError>>;
}

// $end
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ export class UriResolutionContext implements IUriResolutionContext {
}

createSubContext(): IUriResolutionContext {
return new UriResolutionContext(this._resolvingUriMap, this._history);
const map = new Map<string, boolean>();
// Copy the resolvingUriMap to the new map, so that changes to the new map don't affect the old map
for (const key of this._resolvingUriMap.keys()) {
this._resolvingUriMap.get(key) && map.set(key, true);
}
return new UriResolutionContext(map, []);
}
}
87 changes: 37 additions & 50 deletions packages/js/uri-resolver-extensions/src/UriResolverWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,30 @@
import { UriResolverExtensionFileReader } from "./UriResolverExtensionFileReader";
import { loadResolverExtension } from "./ResolverExtensionLoader";

import {
Uri,
CoreClient,
UriResolverInterface,
IUriResolutionContext,
UriPackageOrWrapper,
getEnvFromUriHistory,
IUriResolver,
} from "@polywrap/core-js";
import { Result, ResultOk } from "@polywrap/result";
import { WasmPackage } from "@polywrap/wasm-js";
import {
ResolverWithHistory,
UriResolutionResult,
} from "@polywrap/uri-resolvers-js";
import { UriResolutionResult } from "@polywrap/uri-resolvers-js";

// $start: UriResolverWrapper
/**
* An IUriResolver that delegates resolution to a wrapper that implements
* the URI Resolver Extension Interface
* */
export class UriResolverWrapper extends ResolverWithHistory<unknown> /* $ */ {
export class UriResolverWrapper implements IUriResolver<unknown> /* $ */ {
// $start: UriResolverWrapper-constructor
/**
* construct a UriResolverWrapper
*
* @param implementationUri - URI that resolves to a URI Resolver Extension implementation
* */
constructor(public readonly implementationUri: Uri) /* $ */ {
super();
}

// $start: UriResolverWrapper-getStepDescription
/**
* A utility function for generating step descriptions to facilitate resolution context updates
*
* @returns text describing the URI resolution step
* */
protected getStepDescription = (): string /* $ */ =>
`ResolverExtension (${this.implementationUri.uri})`;
constructor(public readonly implementationUri: Uri) /* $ */ {}

// $start: UriResolverWrapper-_tryResolverUri
/**
Expand All @@ -51,7 +36,7 @@ export class UriResolverWrapper extends ResolverWithHistory<unknown> /* $ */ {
* @param resolutionContext - the current URI resolution context
* @returns A Promise with a Result containing either a wrap package, a wrapper, or a URI if successful
*/
protected async _tryResolveUri(
async tryResolveUri(
uri: Uri,
client: CoreClient,
resolutionContext: IUriResolutionContext
Expand All @@ -67,22 +52,29 @@ export class UriResolverWrapper extends ResolverWithHistory<unknown> /* $ */ {
return UriResolutionResult.err(result.error);
}

const uriOrManifest = result.value;

if (uriOrManifest?.uri) {
return UriResolutionResult.ok(new Uri(uriOrManifest.uri));
} else if (uriOrManifest?.manifest) {
const wrapPackage = WasmPackage.from(
uriOrManifest.manifest,
new UriResolverExtensionFileReader(this.implementationUri, uri, client)
);
return getResult(result.value, uri, this.implementationUri, client);
}
}

return UriResolutionResult.ok(uri, wrapPackage);
}
const getResult = (
uriOrManifest: UriResolverInterface.MaybeUriOrManifest | undefined,
uri: Uri,
implementationUri: Uri,
client: CoreClient
): Result<UriPackageOrWrapper, unknown> => {
if (uriOrManifest?.uri) {
return UriResolutionResult.ok(new Uri(uriOrManifest.uri));
} else if (uriOrManifest?.manifest) {
const wrapPackage = WasmPackage.from(
uriOrManifest.manifest,
new UriResolverExtensionFileReader(implementationUri, uri, client)
);

return UriResolutionResult.ok(uri);
return UriResolutionResult.ok(uri, wrapPackage);
}
}

return UriResolutionResult.ok(uri);
};

// $start: UriResolverWrapper-tryResolveUriWithImplementation
/**
Expand All @@ -102,34 +94,29 @@ const tryResolveUriWithImplementation = async (
): Promise<
Result<UriResolverInterface.MaybeUriOrManifest | undefined, unknown>
> /* $ */ => {
const subContext = resolutionContext.createSubContext();
const result = await loadResolverExtension(
uri,
implementationUri,
client,
subContext
);

if (!result.ok) {
return result;
}
const resolverExtensionContext = resolutionContext.createSubContext();

const extensionWrapper = result.value;

const env = getEnvFromUriHistory(subContext.getResolutionPath(), client);
const invokeResult = await client.invokeWrapper<UriResolverInterface.MaybeUriOrManifest>(
const invokeResult = await client.invoke<UriResolverInterface.MaybeUriOrManifest>(
{
wrapper: extensionWrapper,
uri: implementationUri,
method: "tryResolveUri",
args: {
authority: uri.authority,
path: uri.path,
},
env: env,
resolutionContext: resolverExtensionContext,
}
);

resolutionContext.trackStep({
sourceUri: uri,
result: invokeResult.ok
? UriResolutionResult.ok(implementationUri)
: UriResolutionResult.err(invokeResult.error),
description: `ResolverExtension (${implementationUri.uri})`,
subHistory: resolverExtensionContext.getHistory(),
});

if (!invokeResult.ok) {
return invokeResult;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/js/wasm/src/WasmWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
WrapError,
WrapErrorCode,
ErrorSource,
IUriResolutionContext,
typesHandler,
} from "@polywrap/core-js";
import { Result, ResultErr, ResultOk } from "@polywrap/result";
Expand All @@ -43,6 +44,7 @@ export interface State {
invokeResult?: Result<unknown>;
getImplementationsResult?: Uint8Array;
env: Uint8Array;
resolutionContext?: IUriResolutionContext;
}

const EMPTY_ENCODED_OBJECT = msgpackEncode({});
Expand Down Expand Up @@ -163,6 +165,7 @@ export class WasmWrapper implements Wrapper {
: msgpackEncode(args)
: EMPTY_ENCODED_OBJECT,
env: options.env ? msgpackEncode(options.env) : EMPTY_ENCODED_OBJECT,
resolutionContext: options.resolutionContext,
};

const abortWithInvokeAborted = (
Expand Down
1 change: 1 addition & 0 deletions packages/js/wasm/src/imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const createImports = (config: {
method: method,
args: new Uint8Array(args),
encodeResult: true,
resolutionContext: state.resolutionContext,
});

if (result.ok) {
Expand Down
45 changes: 26 additions & 19 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2516,9 +2516,9 @@
integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==

"@types/lodash@^4.14.182":
version "4.14.192"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.192.tgz#5790406361a2852d332d41635d927f1600811285"
integrity sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A==
version "4.14.194"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.194.tgz#b71eb6f7a0ff11bff59fc987134a093029258a76"
integrity sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==

"@types/minimatch@*", "@types/minimatch@^5.1.2":
version "5.1.2"
Expand Down Expand Up @@ -3536,9 +3536,9 @@ camelcase@^6.0.0:
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==

caniuse-lite@^1.0.30001449:
version "1.0.30001478"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001478.tgz#0ef8a1cf8b16be47a0f9fc4ecfc952232724b32a"
integrity sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw==
version "1.0.30001480"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz#9bbd35ee44c2480a1e3a3b9f4496f5066817164a"
integrity sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==

capture-exit@^2.0.0:
version "2.0.0"
Expand Down Expand Up @@ -4357,9 +4357,9 @@ electron-fetch@^1.7.2:
encoding "^0.1.13"

electron-to-chromium@^1.4.284:
version "1.4.362"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.362.tgz#1dfd7a076fc4785a16941f06410d0668e1a7a1aa"
integrity sha512-PYzAoScDfUcAwZfJQvr6hK2xXzLsMocj/Wuz6LpW6TZQNVv9TflBSB+UoEPuFujc478BgAxCoCFarcVPmjzsog==
version "1.4.366"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.366.tgz#48d400f9c4af8e80f7bbad0d18730c165d43155e"
integrity sha512-XjC4pyf1no8kJe24nUfyexpWwiGRbZWXU/KbprSEvXcTXUlr3Zr5vK3lQt2to0ttpMhAc3iENccwPSKbnEW2Fg==

elliptic@6.5.4:
version "6.5.4"
Expand Down Expand Up @@ -4606,9 +4606,9 @@ eslint-import-resolver-node@^0.3.4:
resolve "^1.22.1"

eslint-module-utils@^2.6.0:
version "2.7.4"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974"
integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==
version "2.8.0"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49"
integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==
dependencies:
debug "^3.2.7"

Expand Down Expand Up @@ -7286,9 +7286,9 @@ long@^4.0.0:
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==

long@^5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/long/-/long-5.2.1.tgz#e27595d0083d103d2fa2c20c7699f8e0c92b897f"
integrity sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==
version "5.2.3"
resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==

lru-cache@^5.1.1:
version "5.1.1"
Expand Down Expand Up @@ -9315,13 +9315,20 @@ semver@7.3.8:
dependencies:
lru-cache "^6.0.0"

semver@7.4.0, semver@7.x, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
semver@7.4.0:
version "7.4.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.4.0.tgz#8481c92feffc531ab1e012a8ffc15bdd3a0f4318"
integrity sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==
dependencies:
lru-cache "^6.0.0"

semver@7.x, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
version "7.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0"
integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==
dependencies:
lru-cache "^6.0.0"

semver@^6.0.0, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
Expand Down Expand Up @@ -10343,9 +10350,9 @@ upath@^2.0.1:
integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==

update-browserslist-db@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3"
integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==
version "1.0.11"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"
integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==
dependencies:
escalade "^3.1.1"
picocolors "^1.0.0"
Expand Down