Skip to content

Commit

Permalink
Add documentation comments for ko.observable handling annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
exyi committed Nov 3, 2024
1 parent 69df69d commit 79963b5
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -261,19 +261,25 @@ public ViewModelInfoAnnotation(Type type, bool isControl, BindingExtensionParame
}
}

/// <summary> Specified if properties of the current object are wrapped in knockout observables or not. Observability of the current value is not specified in this annotation, but using <see cref="ResultIsObservableAnnotation" />. </summary>
public sealed record JsObjectObservableMap: IEquatable<JsObjectObservableMap>
{
/// <summary> The default value for all descendants, unless overriden using the other properties </summary>
/// <summary> The default value for all descendants, unless overridden using the other properties. If null, the default nullability for the current expression will be used. </summary>
public bool? ContainsObservables { get; set; }

/// <summary> Default value for all properties. Null means that `ContainsObservables` is assumed to be the same as the parent's </summary>
public JsObjectObservableMap? DefaultChild { get; set; }

/// <summary> Observable mapping for child objects. </summary>
public Dictionary<string, JsObjectObservableMap>? ChildObjects { get; set; }

/// <summary> Specifies if the specific property is ko.observable or not. Does not include more nested properties, that is specified in the <see cref="ChildObjects" /> property. </summary>
public Dictionary<string, bool>? PropertyIsObservable { get; set; }

/// <summary> If <paramref name="name" /> is null, returns the default property observability. </summary>
public bool? IsPropertyObservable(string? name) => name is {} && PropertyIsObservable?.TryGetValue(name, out var value) == true ? value : ContainsObservables;

/// <summary> If <c>objectPath[x]</c> is null, returns the default property observability. </summary>
public bool? IsPropertyObservable(ReadOnlySpan<string?> objectPath)
{
if (objectPath.Length == 0) return null;
Expand All @@ -297,6 +303,7 @@ public JsObjectObservableMap GetChildObject(ReadOnlySpan<string?> objectPath)
return current;
}

/// <summary> Replaces properties in this with non-default properties in <paramref name="override"/> </summary>
public JsObjectObservableMap OverrideWith(JsObjectObservableMap? @override)
{
if (@override is null || @override == Default || this == @override || this == Default) return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,37 +178,43 @@ public override void VisitSymbolicParameter(JsSymbolicParameter expr)
}
}

/// <summary> Indicates that this invocation only unwraps a knockout observable and was automatically inserted by <see cref="KnockoutObservableHandlingVisitor" /> </summary>
public sealed class ObservableUnwrapInvocationAnnotation
{
private ObservableUnwrapInvocationAnnotation() { }
public static ObservableUnwrapInvocationAnnotation Instance = new ObservableUnwrapInvocationAnnotation();
}
/// <summary> Indicates that this invocation is a knockout observable value assignment and was automatically inserted by <see cref="KnockoutObservableHandlingVisitor" /> </summary>
public sealed class ObservableSetterInvocationAnnotation
{
private ObservableSetterInvocationAnnotation() { }
public static ObservableSetterInvocationAnnotation Instance = new ObservableSetterInvocationAnnotation();
}
/// <summary> Result of the annotated expression is always a knockout observable. DotVVM will automatically unwrap the observable, unless the <see cref="ShouldBeObservableAnnotation" /> is also specified. </summary>
public sealed class ResultIsObservableAnnotation
{
private ResultIsObservableAnnotation() { }
public static ResultIsObservableAnnotation Instance = new ResultIsObservableAnnotation();
}
/// <summary> Result is a knockout observable array. </summary>
public sealed class ResultIsObservableArrayAnnotation
{
private ResultIsObservableArrayAnnotation() { }
public static ResultIsObservableArrayAnnotation Instance = new ResultIsObservableArrayAnnotation();
}
/// <summary> Result of the annotated expression may or may not be a knockout observable. DotVVM will automatically unwrap the observable, unless the <see cref="ShouldBeObservableAnnotation" /> is also specified. </summary>
public sealed class ResultMayBeObservableAnnotation
{
private ResultMayBeObservableAnnotation() { }
public static ResultMayBeObservableAnnotation Instance = new ResultMayBeObservableAnnotation();
}
/// <summary> This node should return observable - instructs the <see cref="KnockoutObservableHandlingVisitor" /> to not unwrap the node and the <see cref="JsViewModelPropertyAdjuster" /> to not use .state in the subexpression. </summary>
public sealed class ShouldBeObservableAnnotation
{
private ShouldBeObservableAnnotation() { }
public static ShouldBeObservableAnnotation Instance = new ShouldBeObservableAnnotation();
}
/// Instruct the <see cref="KnockoutObservableHandlingVisitor" /> to process the node after it's children are resolved and before it is handled itself by the rules
/// <summary> Instruct the <see cref="KnockoutObservableHandlingVisitor" /> to process the node after it's children are resolved and before it is handled itself by the rules </summary>
public sealed class ObservableTransformationAnnotation
{
public readonly Func<JsExpression, JsExpression> TransformExpression;
Expand All @@ -217,7 +223,7 @@ public ObservableTransformationAnnotation(Func<JsExpression, JsExpression> trans
TransformExpression = transformExpression;
}

/// Makes sure that the observable is fully wrapped in observable (i.e. wraps the expression in `ko.pureComputed(...)` when needed)
/// <summary> Makes sure that the observable is fully wrapped in observable (i.e. wraps the expression in `ko.pureComputed(...)` when needed) </summary>
public static readonly ObservableTransformationAnnotation EnsureWrapped = new ObservableTransformationAnnotation(JsAstHelpers.EnsureObservableWrapped);
}
}
3 changes: 1 addition & 2 deletions src/Framework/Framework/Hosting/DotvvmPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,7 @@ Cross site iframe are disabled in this application.
await context.RejectRequest($"""
Pages can not be loaded using Javascript for security reasons.
Try refreshing the page to get rid of the error.
If you are the developer, you can disable this check by setting DotvvmConfiguration.Security.VerifySecFetchForPages.ExcludeRoute("{route}"). [dest: {dest}, site: {site}].
Note that this security check is not compatible with JavaScript-based prefetching, such as TurboLinks, Cloudflare Speed Brain, or similar, and you'll need to disable one of them. The check is "only" a deference-in-depth measure against XSS, and disabling it is not a vulnerability by itself.
If you are the developer, you can disable this check by setting DotvvmConfiguration.Security.VerifySecFetchForPages.ExcludeRoute("{route}"). [dest: {dest}, site: {site}]
""");
if (site != "same-origin")
await context.RejectRequest($"Cross site SPA requests are disabled.");
Expand Down

0 comments on commit 79963b5

Please sign in to comment.