// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.IO;
using System.Threading;
using Microsoft.ClearScript.JavaScript;
using Microsoft.ClearScript.Util;
namespace Microsoft.ClearScript
{
///
/// Contains meta-information for a document.
///
public struct DocumentInfo
{
private static long lastUniqueId;
private readonly string name;
private DocumentCategory category;
private ulong uniqueId;
///
/// Initializes a new structure with the specified document name.
///
/// The document name.
public DocumentInfo(string name)
: this()
{
this.name = name;
uniqueId = Interlocked.Increment(ref lastUniqueId).ToUnsigned();
}
///
/// Initializes a new structure with the specified document URI.
///
/// The document URI.
public DocumentInfo(Uri uri)
: this()
{
MiscHelpers.VerifyNonNullArgument(uri, "uri");
Uri = uri.IsAbsoluteUri ? uri : new Uri(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + uri);
name = Path.GetFileName(Uri.AbsolutePath);
uniqueId = Interlocked.Increment(ref lastUniqueId).ToUnsigned();
}
///
/// Gets the document's name.
///
///
/// This property always returns a non-blank string. If a null or blank document name was
/// specified at instantiation time, this property returns a default document name.
///
public string Name => MiscHelpers.EnsureNonBlank(name, Category.DefaultName);
///
/// Gets the document's URI.
///
///
/// This property returns null if a URI was not specified at instantiation time.
///
public Uri Uri { get; }
///
/// Gets or sets an optional source map URI for the document.
///
public Uri SourceMapUri { get; set; }
///
/// Gets or sets the document's category.
///
public DocumentCategory Category
{
get => category ?? DocumentCategory.Script;
set => category = value;
}
///
/// Gets or sets optional document attributes.
///
public DocumentFlags? Flags { get; set; }
///
/// Gets or sets an optional context callback for the document.
///
///
///
/// This property currently applies only to modules. If specified, the callback is invoked
/// the first time the module attempts to retrieve its context information. The properties
/// it returns are made available to the module implementation. This mechanism can be used
/// to expose host resources selectively, securely, and without polluting the script
/// engine's global namespace.
///
///
/// Use
/// import.meta
/// to access the context information of a JavaScript
/// module. In a module, use module.meta.
///
///
public DocumentContextCallback ContextCallback { get; set; }
internal UniqueDocumentInfo MakeUnique(ScriptEngine engine)
{
return MakeUnique(engine.DocumentNameManager);
}
internal UniqueDocumentInfo MakeUnique(ScriptEngine engine, DocumentFlags? defaultFlags)
{
return MakeUnique(engine.DocumentNameManager, defaultFlags);
}
internal UniqueDocumentInfo MakeUnique(IUniqueNameManager manager)
{
return MakeUnique(manager, null);
}
internal UniqueDocumentInfo MakeUnique(IUniqueNameManager manager, DocumentFlags? defaultFlags)
{
var info = this;
if (!info.Flags.HasValue && defaultFlags.HasValue)
{
info.Flags = defaultFlags;
}
if (uniqueId < 1)
{
uniqueId = Interlocked.Increment(ref lastUniqueId).ToUnsigned();
}
var uniqueName = manager.GetUniqueName(Name, Category.DefaultName);
if (info.Flags.GetValueOrDefault().HasFlag(DocumentFlags.IsTransient))
{
uniqueName += " [temp]";
}
return new UniqueDocumentInfo(info, uniqueId, uniqueName);
}
}
}