diff --git a/autobuild.xml b/autobuild.xml
index feca45d6d8..3f07900e58 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1326,18 +1326,6 @@
lsl_definitions
- source_type
- git
+ license
+ MIT
+ license_file
+ LICENSES/lsl_definitions.txt
+ copyright
+ Copyright (c) 2026, Linden Lab
+ version
+ 0.6.3
use_scm_version
true
+ name
+ lsl_definitions
vcs_branch
refs/tags/v0.4.1
vcs_revision
03006fb488cba2bae502e9baed051bfc8d00144d
vcs_url
git://github.com/secondlife/lsl-definitions.git
- version
- 0.4.1
+ canonical_repo
+ https://github.com/secondlife/lsl-definitions
+ description
+ LSL definitions
+ source_type
+ git
meshoptimizer
@@ -2473,16 +2473,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
webrtc
- canonical_repo
- https://github.com/secondlife/3p-webrtc-build
- copyright
- Copyright (c) 2011, The WebRTC project authors. All rights reserved.
- license
- MIT
- license_file
- LICENSES/webrtc-license.txt
- name
- webrtc
platforms
darwin64
@@ -2528,14 +2518,24 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
windows64
+ license
+ MIT
+ license_file
+ LICENSES/webrtc-license.txt
+ copyright
+ Copyright (c) 2011, The WebRTC project authors. All rights reserved.
+ version
+ m137.7151.04.23.22004231636
+ name
+ webrtc
vcs_branch
secondlife
vcs_revision
d3f62d32bac8694d3c7423c731ae30c113bf6a11
vcs_url
https://github.com/secondlife/3p-webrtc-build
- version
- m137.7151.04.23.22004231636
+ canonical_repo
+ https://github.com/secondlife/3p-webrtc-build
xxhash
@@ -2813,18 +2813,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
websocketpp
- canonical_repo
- https://github.com/secondlife/3p-websocketpp
- copyright
- Copyright (c) 2014, Peter Thorson
- description
- WebSocket++ is a C++ header only library for interacting with WebSocket servers and clients.
- license
- websocketpp
- license_file
- LICENSES/websocketpp.txt
- name
- websocketpp
platforms
common
@@ -2842,14 +2830,26 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
common
+ license
+ websocketpp
+ license_file
+ LICENSES/websocketpp.txt
+ copyright
+ Copyright (c) 2014, Peter Thorson
+ version
+ 0.8.2.24525603568
+ name
+ websocketpp
vcs_branch
refs/tags/v0.8.2
vcs_revision
bdcf1453101976fc4dc26a62c87bc98c12e9c6dc
vcs_url
git://github.com/secondlife/3p-websocketpp.git
- version
- 0.8.2.24525603568
+ canonical_repo
+ https://github.com/secondlife/3p-websocketpp
+ description
+ WebSocket++ is a C++ header only library for interacting with WebSocket servers and clients.
package_description
diff --git a/doc/external-editor-json-rpc.md b/doc/external-editor-json-rpc.md
index b8c7fa69e3..202f1e5b29 100644
--- a/doc/external-editor-json-rpc.md
+++ b/doc/external-editor-json-rpc.md
@@ -1,6 +1,6 @@
# Viewer to External Editor JSON-RPC
Message Interfaces Documentation
-This document describes all the message interfaces defined in for WebSocket communication between the Second Life viewer and an external editor such as a VSCode extension.
+This document describes all the message interfaces defined for WebSocket communication between the Second Life viewer and an external editor such as a VSCode extension.
## Table of Contents
@@ -15,10 +15,13 @@ This document describes all the message interfaces defined in for WebSocket comm
- [SyntaxChange](#syntaxchange)
- [Language Syntax ID Request](#language-syntax-id-request)
- [Language Syntax Request](#language-syntax-request)
+ - [Language Syntax Cache List](#language-syntax-cache-list)
+ - [Language Syntax Cache Get](#language-syntax-cache-get)
- [Script Subscription Interfaces](#script-subscription-interfaces)
- [ScriptSubscribe](#scriptsubscribe)
- [ScriptSubscribeResponse](#scriptsubscriberesponse)
- [ScriptUnsubscribe](#scriptunsubscribe)
+ - [ScriptList](#scriptlist)
- [Compilation Interfaces](#compilation-interfaces)
- [CompilationError](#compilationerror)
- [CompilationResult](#compilationresult)
@@ -33,7 +36,7 @@ This document describes all the message interfaces defined in for WebSocket comm
1. **Connection Establishment:**
- - Viewer sends `session.handshake` notification with `SessionHandshake` data
+ - Viewer sends `session.handshake` call with `SessionHandshake` data
- Extension responds with `SessionHandshakeResponse`
- Viewer confirms with `session.ok` notification
@@ -41,7 +44,7 @@ This document describes all the message interfaces defined in for WebSocket comm
- Extension makes `language.syntax.id` call to get current syntax version
- Extension makes `language.syntax` calls with different `kind` parameters to get specific language data
- - Viewer responds with `LanguageInfo` data containing the requested information
+ - Viewer responds with a `LanguageInfo` object containing the requested definitions
3. **Script Subscription Management:**
@@ -65,17 +68,23 @@ This document describes all the message interfaces defined in for WebSocket comm
| Method | Direction | Type | Interface/Parameters |
| ------------------------------- | ------------------ | ------------ | -------------------------- |
-| `session.handshake` | Viewer → Extension | Notification | `SessionHandshake` |
+| `session.handshake` | Viewer → Extension | Call | `SessionHandshake` |
| `session.handshake` (response) | Extension → Viewer | Response | `SessionHandshakeResponse` |
| `session.ok` | Viewer → Extension | Notification | _(no interface)_ |
| `session.disconnect` | Bidirectional | Notification | `SessionDisconnect` |
| `script.subscribe` | Extension → Viewer | Call | `ScriptSubscribe` |
| `script.subscribe` (response) | Viewer → Extension | Response | `ScriptSubscribeResponse` |
| `script.unsubscribe` | Viewer → Extension | Notification | `ScriptUnsubscribe` |
+| `script.list` | Extension → Viewer | Call | _(no parameters)_ |
+| `script.list` (response) | Viewer → Extension | Response | `ScriptList` |
| `language.syntax.id` | Extension → Viewer | Call | _(no parameters)_ |
| `language.syntax.id` (response) | Viewer → Extension | Response | `{ id: string }` |
| `language.syntax` | Extension → Viewer | Call | `{ kind: string }` |
| `language.syntax` (response) | Viewer → Extension | Response | `LanguageInfo` |
+| `language.syntax.cache` | Extension → Viewer | Call | _(no parameters)_ |
+| `language.syntax.cache` (response) | Viewer → Extension | Response | `SyntaxCacheList` |
+| `language.syntax.get` | Extension → Viewer | Call | `{ filename: string, as_json?: boolean }` |
+| `language.syntax.get` (response) | Viewer → Extension | Response | `SyntaxCacheFile` |
| `language.syntax.change` | Viewer → Extension | Notification | `SyntaxChange` |
| `script.compiled` | Viewer → Extension | Notification | `CompilationResult` |
| `runtime.debug` | Viewer → Extension | Notification | `RuntimeDebug` |
@@ -85,9 +94,9 @@ This document describes all the message interfaces defined in for WebSocket comm
### SessionHandshake
-**JSON-RPC Method:** `session.handshake` (notification from viewer)
+**JSON-RPC Method:** `session.handshake` (call from viewer)
-The initial handshake message sent by the viewer to establish a connection.
+The initial handshake call sent by the viewer to establish a session.
```typescript
interface SessionHandshake {
@@ -112,10 +121,13 @@ interface SessionHandshake {
- `viewer_version`: Version string of the viewer
- `agent_id`: Unique identifier for the user/agent
- `agent_name`: Human-readable name of the agent
-- `challenge` (optional): Security challenge string for authentication
-- `languages`: Array of supported scripting languages (e.g., ["lsl", "luau"])
-- `syntax_id`: Current active syntax/language identifier
-- `features`: Dictionary of feature flags indicating viewer capabilities
+- `challenge` (optional): Path to a temporary file on the local filesystem containing a UUID. The client must read this file and return the UUID as `challenge_response` to authenticate the connection.
+- `languages`: Array of supported scripting languages (e.g., `["lsl", "luau"]`)
+- `syntax_id`: Current active syntax identifier as a UUID string
+- `features`: Dictionary of feature flags indicating viewer capabilities. Known flags:
+ - `live_sync`: Viewer supports live script synchronisation with the external editor
+ - `compilation`: Viewer will forward compilation results via `script.compiled`
+ - `syntax_cache`: Viewer supports `language.syntax.cache` and `language.syntax.get` for retrieving syntax definition files
### SessionHandshakeResponse
@@ -131,6 +143,8 @@ interface SessionHandshakeResponse {
challenge_response?: string;
languages: string[];
features: { [feature: string]: boolean };
+ script_name?: string;
+ script_language?: string;
}
```
@@ -139,15 +153,17 @@ interface SessionHandshakeResponse {
- `client_name`: Name of the client (VS Code extension)
- `client_version`: Fixed version "1.0" of the client
- `protocol_version`: Protocol version the client supports
-- `challenge_response` (optional): Response to the security challenge if provided
+- `challenge_response` (optional): The UUID read from the temporary file identified by the `challenge` field in the handshake. Must be provided if `challenge` was present, otherwise the connection will be closed.
- `languages`: Array of languages supported by the client
- `features`: Dictionary of features supported by the client
+- `script_name` (optional): Name of the script currently open in the editor
+- `script_language` (optional): Language of the script currently open in the editor (e.g. `"lsl"`, `"luau"`)
### Session OK
**JSON-RPC Method:** `session.ok` (notification from viewer)
-Confirmation notification sent by the viewer after successful handshake completion. This interface has no defined structure as it appears to be a simple confirmation message.
+Confirmation notification sent by the viewer after successful handshake completion. No parameters are sent with this notification.
### SessionDisconnect
@@ -164,7 +180,12 @@ interface SessionDisconnect {
**Fields:**
-- `reason`: Numeric code indicating the reason for disconnection
+- `reason`: Numeric code indicating the reason for disconnection:
+ - `0`: Normal closure
+ - `1`: Editor closed
+ - `2`: Protocol error
+ - `3`: Connection timeout
+ - `4`: Internal server error
- `message`: Human-readable description of the disconnect reason
## Language and Syntax Interfaces
@@ -183,7 +204,7 @@ interface SyntaxChange {
**Fields:**
-- `id`: Identifier for the new syntax/language
+- `id`: UUID string identifying the new syntax version
### Language Syntax ID Request
@@ -191,63 +212,130 @@ interface SyntaxChange {
Requests the current active language syntax identifier from the viewer. This method takes no parameters.
-**Response:** Returns an object with an `id` field containing the current syntax identifier.
+**Response:** Returns `{ id: string }` where `id` is the current syntax version as a UUID string.
### Language Syntax Request
**JSON-RPC Method:** `language.syntax` (call from extension to viewer)
-Requests detailed syntax information for a specific language kind.
+Requests the in-memory keyword definitions for a specific language. These definitions are the deserialized, viewer-processed form of the syntax data for the current region.
**Parameters:**
```typescript
{
- kind: string; // The type of syntax information requested
+ kind: string; // The language whose definitions to retrieve
}
```
-**Fields:**
+**Valid `kind` values:**
-- `kind`: The type of syntax information to retrieve (e.g., "functions", "constants", "events", "types.luau")
+| Value | Description |
+| ----------- | ----------------------------------------- |
+| `"defs.lsl"` | Returns the LSL keyword definitions |
+| `"defs.lua"` | Returns the Luau keyword definitions |
-**Response:** Returns `LanguageInfo` data containing the requested syntax information:
+**Response:**
```typescript
interface LanguageInfo {
id: string;
- lslDefs?: {
- controls?: any;
- types?: any;
- constants?: { [name: string]: ConstantDef };
- events?: { [name: string]: FunctionDef };
- functions?: { [name: string]: FunctionDef };
- };
- luaDefs?: {
- modules?: { [name: string]: TypeDef };
- classes?: { [name: string]: TypeDef };
- aliases?: { [name: string]: TypeDef };
- functions?: { [name: string]: FunctionDef };
- };
+ defs?: object; // Present only on success
+ success: boolean;
+ error?: string; // Present only on failure
+}
+```
+
+**Response Fields:**
+
+- `id`: The current syntax version identifier
+- `defs` (optional): The keyword definitions object. Only present when `success` is `true`. Structure varies by language.
+- `success`: Whether the definitions were found and returned successfully
+- `error` (optional): Human-readable error description. Only present when `success` is `false`
+
+**Error cases:**
+
+- No `kind` parameter supplied: `success: false`, `error: "No syntax category specified"`
+- Unknown `kind` value: `success: false`, `error: "Unknown syntax category requested"`
+
+### Language Syntax Cache List
+
+**JSON-RPC Method:** `language.syntax.cache` (call from extension to viewer)
+
+Requests the list of file names currently held in the `LLSyntaxDefCache`. This provides the extension with the available syntax definition file names that can subsequently be retrieved with `language.syntax.get`. This method takes no parameters.
+
+**Response:**
+
+```typescript
+interface SyntaxCacheList {
+ files: string[]; // Array of file names (e.g. ["lsl_keywords.xml", "slua_definitions.yaml"])
+ success: boolean;
}
```
**Response Fields:**
-- `id`: Version identifier for the language syntax
-- `lslDefs` (optional): LSL-specific language definitions containing:
- - `controls` (optional): Control flow and language constructs
- - `types` (optional): LSL type definitions
- - `constants` (optional): Object containing constant definitions keyed by constant name
- - `events` (optional): Object containing event definitions keyed by event name
- - `functions` (optional): Object containing function definitions keyed by function name
-- `luaDefs` (optional): Lua-specific language definitions containing:
- - `modules` (optional): Module type definitions keyed by module name
- - `classes` (optional): Class type definitions keyed by class name
- - `aliases` (optional): Type alias definitions keyed by alias name
- - `functions` (optional): Function definitions keyed by function name
-
-The specific sections returned depend on the `kind` parameter and the active language context.
+- `files`: Array of file name strings, each of which can be passed as the `filename` parameter to `language.syntax.get`
+- `success`: Whether the request was handled successfully
+
+**Known cache files:**
+
+| File name | Description |
+| -------------------------------- | ---------------------------------------------------- |
+| `builtins.txt` | LSL built-in keyword list in plain text format |
+| `lsl_definitions.yaml` | LSL language definitions in YAML format |
+| `lsl_keywords.xml` | LSL keyword definitions in LLSD XML format |
+| `lsl_keywords_pretty.xml` | LSL keyword definitions in formatted LLSD XML format |
+| `slua_default.d.luau` | Luau type definition file for editor tooling |
+| `slua_default.docs.json` | Luau documentation data in JSON format |
+| `slua_definitions.yaml` | Luau language definitions in YAML format |
+| `slua_keywords.xml` | Luau keyword definitions in LLSD XML format |
+| `slua_keywords_pretty.xml` | Luau keyword definitions in formatted LLSD XML format |
+| `slua_selene.yml` | Luau Selene linter configuration in YAML format |
+
+Not all files may be present in every cache — the actual list returned by `language.syntax.cache` reflects only what is available on the viewer's local filesystem at the time of the request.
+
+### Language Syntax Cache Get
+
+**JSON-RPC Method:** `language.syntax.get` (call from extension to viewer)
+
+Requests the content of a specific file from the syntax definition cache. The file name must be one of the names returned by a prior `language.syntax.cache` call. Content is returned either as a raw text string or as a parsed JSON/LLSD object depending on the `as_json` parameter.
+
+**Parameters:**
+
+```typescript
+{
+ filename: string; // The file name to retrieve, as returned by language.syntax.cache
+ as_json?: boolean; // Optional. If true, content is returned as a parsed object rather than raw text
+}
+```
+
+**Fields:**
+
+- `filename`: The file name to retrieve (e.g. `"lsl_keywords.xml"`, `"slua_definitions.yaml"`)
+- `as_json` (optional): When `true`, the file is deserialized and returned as a structured object in `content`. When omitted or `false`, `content` is the raw text of the file.
+
+**Response:**
+
+```typescript
+interface SyntaxCacheFile {
+ content?: string | object; // Present only on success. String if as_json is false/omitted, object if as_json is true
+ success: boolean;
+ error?: string; // Present only on failure
+}
+```
+
+**Response Fields:**
+
+- `content`: The file content. Only present when `success` is `true`. Is a raw text string when `as_json` is omitted or `false`; is a parsed object when `as_json` is `true`.
+- `success`: Whether the file was found and read successfully
+- `error` (optional): Human-readable error description. Only present when `success` is `false`
+
+**Error cases:**
+
+- No `filename` parameter supplied: `success: false`, `error: "No filename specified"`
+- Name not found in cache: `success: false`, `error: "Requested syntax cache file not found"`
+- File could not be loaded: `success: false`, `error: "Failed to load syntax cache file"` (or `"Failed to load and format syntax cache file."` when `as_json` is `true`)
## Script Subscription Interfaces
@@ -283,7 +371,6 @@ interface ScriptSubscribeResponse {
success: boolean;
status: number;
object_id?: string;
- object_name?: string;
item_id?: string;
message?: string;
}
@@ -293,9 +380,14 @@ interface ScriptSubscribeResponse {
- `script_id`: The script identifier that was subscribed to
- `success`: Whether the subscription was successful
-- `status`: Numeric status code indicating the result
-- `object_id` (optional): The in-world ID of the object containing the script
-- `object_name` (optional): The name of the object containing the script.
+- `status`: Numeric status code indicating the result:
+ - `0`: Success
+ - `1`: Invalid editor — the script editor panel is no longer open
+ - `2`: Invalid subscription — no subscription found for the given `script_id`
+ - `3`: Already subscribed — another connection is already subscribed to this script
+ - `4`: Internal server error
+- `object_id` (optional): The in-world UUID of the object containing the script
+- `item_id` (optional): The inventory item UUID of the script within the object
- `message` (optional): Additional information about the subscription result
### ScriptUnsubscribe
@@ -314,6 +406,28 @@ interface ScriptUnsubscribe {
- `script_id`: Unique identifier for the script to unsubscribe from
+### ScriptList
+
+**JSON-RPC Method:** `script.list` (call from extension to viewer)
+
+Requests the list of all scripts currently open and tracked by the viewer, along with the viewer's temp directory. This is intended for use by a file watcher tool that needs to discover which script temp files are active without going through the full `script.subscribe` flow. This method takes no parameters.
+
+**Response:**
+
+```typescript
+interface ScriptList {
+ temp_dir: string;
+ script_ids: string[];
+ success: boolean;
+}
+```
+
+**Response Fields:**
+
+- `temp_dir`: The absolute path to the viewer's temp directory where live-sync script files are written. Combined with a `script_id`, the caller can locate the corresponding temp file on disk.
+- `script_ids`: Array of script ID strings for all currently subscribed scripts, across all active connections.
+- `success`: Always `true`.
+
## Compilation Interfaces
### CompilationError
@@ -324,17 +438,19 @@ Individual compilation error record.
interface CompilationError {
row: number;
column: number;
- level: "ERROR";
+ level: string;
message: string;
+ format?: "lsl"; // Present only for LSL compilation errors
}
```
**Fields:**
-- `row`: Line number where the error occurred (0-based or 1-based depending on context)
-- `column`: Column position of the error
-- `level`: Severity level (currently only "ERROR" is defined)
+- `row`: Line number where the error occurred (1-based for both LSL and Luau)
+- `column`: Column position of the error (1-based for LSL; always `0` for Luau as the compiler does not provide column information)
+- `level`: Compiler severity string (e.g. `"ERROR"`, `"WARNING"`)
- `message`: Error description
+- `format` (optional): Present and set to `"lsl"` for LSL compilation errors; absent for Luau errors
### CompilationResult
@@ -405,10 +521,10 @@ interface RuntimeError {
- `script_id`: Unique identifier for the script that encountered the error
- `object_id`: Unique identifier for the object containing the script
- `object_name`: Human-readable name of the object
-- `message`: Error message description
-- `error`: Specific error type or code
-- `line`: Line number where the error occurred
-- `stack` (optional): Stack trace information if available
+- `message`: The full raw chat text of the runtime error message as received from the simulator
+- `error`: Extracted error description. Currently always an empty string — runtime error extraction from the simulator's multi-message format is not yet fully implemented.
+- `line`: Line number where the error occurred. Currently always `0` for the same reason.
+- `stack` (optional): Stack trace lines if they could be extracted from the error message
## Handler and Configuration Interfaces
@@ -436,7 +552,7 @@ interface WebSocketHandlers {
- `onHandshake`: Handler for initial handshake message, returns handshake response
- `onHandshakeOk`: Handler called when handshake is successfully completed
- `onDisconnect`: Handler for disconnect notifications
-- `onSubscribe`: Handler for script subscription requests from viewer, returns subscription response
+- `onSubscribe`: Handler called when the extension sends a `script.subscribe` request, returns subscription response
- `onUnsubscribe`: Handler for script unsubscription notifications from viewer
- `onSyntaxChange`: Handler for syntax change notifications
- `onConnectionClosed`: Handler called when connection is closed
diff --git a/indra/cmake/LSLDefinitions.cmake b/indra/cmake/LSLDefinitions.cmake
index ae0eeebb7e..1a9a477118 100644
--- a/indra/cmake/LSLDefinitions.cmake
+++ b/indra/cmake/LSLDefinitions.cmake
@@ -3,7 +3,7 @@ include(Prebuilt)
use_prebuilt_binary(lsl_definitions)
-configure_file("${AUTOBUILD_INSTALL_DIR}/lsl_definitions/lsl_keywords_pretty.xml"
+configure_file("${AUTOBUILD_INSTALL_DIR}/lsl_definitions/lsl_keywords.xml"
"${CMAKE_SOURCE_DIR}/newview/app_settings/keywords_lsl_default.xml" COPYONLY)
-configure_file("${AUTOBUILD_INSTALL_DIR}/lsl_definitions/slua_keywords_pretty.xml"
+configure_file("${AUTOBUILD_INSTALL_DIR}/lsl_definitions/lua_keywords.xml"
"${CMAKE_SOURCE_DIR}/newview/app_settings/keywords_lua_default.xml" COPYONLY)
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index b24e5e4fcc..f18af1f18e 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -39,7 +39,7 @@
#include "llfilesystem.h"
#include "message.h" // for getting the port
-
+#include "llstl.h"
using namespace LLCore;
@@ -112,15 +112,17 @@ bool responseToLLSD(HttpResponse * response, bool log, LLSD & out_llsd)
{
// Convert response to LLSD
BufferArray * body(response->getBody());
- if (!body || !body->size())
+ size_t body_size(body ? body->size() : 0);
+ if (!body || !body_size)
{
return false;
}
LLCore::BufferArrayStream bas(body);
LLSD body_llsd;
- S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas, log));
- if (LLSDParser::PARSE_FAILURE == parse_status){
+
+ if (!LLSDSerialize::deserialize(body_llsd, bas, body_size))
+ {
return false;
}
out_llsd = body_llsd;
@@ -409,28 +411,6 @@ LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:
result = parseBody(response, success);
-#if 0
- bool parsed = !((response->getBodySize() == 0) ||
- !LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, result));
-
- if (!parsed)
- {
- // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
- LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
- const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
-
- if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
- {
- std::string thebody = LLCoreHttpUtil::responseToString(response);
- LL_WARNS("CoreHTTP") << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
- << " body: " << thebody << LL_ENDL;
-
- // Replace the status with a new one indicating the failure.
- status = LLCore::HttpStatus(499, "Failed to deserialize LLSD.");
- }
- }
-#endif
-
if (!success)
{
#if 1
@@ -955,7 +935,6 @@ LLSD HttpCoroutineAdapter::getJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
return getAndSuspend_(request, url, options, headers, httpHandler);
}
-
LLSD HttpCoroutineAdapter::getAndSuspend_(LLCore::HttpRequest::ptr_t &request,
const std::string & url,
LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h
index 3dbfd6f00d..8fa638fd6e 100644
--- a/indra/llmessage/llcorehttputil.h
+++ b/indra/llmessage/llcorehttputil.h
@@ -483,7 +483,6 @@ class HttpCoroutineAdapter
headers);
}
-
/// Execute a DELETE transaction on the supplied URL and yield execution of
/// the coroutine until a result is available.
///
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 4be89df283..bd2b484e7a 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1687,7 +1687,6 @@ set(viewer_APPSETTINGS_FILES
app_settings/std_bump.ini
app_settings/toolbars.xml
app_settings/trees.xml
- app_settings/types_lua_default.xml
app_settings/viewerart.xml
app_settings/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
diff --git a/indra/newview/app_settings/types_lua_default.xml b/indra/newview/app_settings/types_lua_default.xml
deleted file mode 100644
index cb40ec3d06..0000000000
--- a/indra/newview/app_settings/types_lua_default.xml
+++ /dev/null
@@ -1,5262 +0,0 @@
-
-
-
- version
- 1.0.0
- typeAliases
-
-
- name
- rotation
- definition
-
- kind
- reference
- name
- quaternion
-
- comment
- 'rotation' is an alias for 'quaternion'
-
-
- name
- numeric
- definition
-
- kind
- union
- types
-
- boolean
- number
-
-
-
-
- name
- list
- definition
-
- kind
- array
- elementType
-
- kind
- union
- types
-
- string
- number
- vector
- uuid
- quaternion
- boolean
-
-
-
-
-
- name
- LLDetectedEventName
- definition
-
- kind
- literal-union
- values
-
-
-
-
- name
- LLNonDetectedEventName
- definition
-
- kind
- literal-union
- values
-
-
-
-
- name
- LLEventName
- definition
-
- kind
- union
- types
-
- LLDetectedEventName
- LLNonDetectedEventName
-
-
-
-
- name
- LLEventHandler
- definition
-
- kind
- function
- parameters
-
-
- type
- any
- variadic
- true
-
-
- returnType
- ()
-
-
-
- name
- LLDetectedEventHandler
- definition
-
- kind
- function
- parameters
-
-
- name
- detected
- type
-
- kind
- array
- elementType
- LLDetectedEvent
-
-
-
- returnType
- ()
-
-
-
- name
- LLTimerEveryCallback
- definition
-
- kind
- function
- parameters
-
-
- name
- scheduled
- type
- number
-
-
- name
- interval
- type
- number
-
-
- returnType
- ()
-
- comment
- Callback type for LLTimers.every() - receives scheduled time and interval
-
-
- name
- LLTimerOnceCallback
- definition
-
- kind
- function
- parameters
-
-
- name
- scheduled
- type
- number
-
-
- returnType
- ()
-
- comment
- Callback type for LLTimers.once() - receives scheduled time
-
-
- name
- LLTimerCallback
- definition
-
- kind
- union
- types
-
- LLTimerEveryCallback
- LLTimerOnceCallback
- (...any) -> ...any
-
-
- comment
- Union of timer callback types
-
-
- name
- OsDateTime
- definition
-
- kind
- table
- properties
-
-
- name
- year
- type
- number
-
-
- name
- month
- type
- number
-
-
- name
- day
- type
- number
-
-
- name
- hour
- type
- number
- optional
- true
-
-
- name
- min
- type
- number
- optional
- true
-
-
- name
- sec
- type
- number
- optional
- true
-
-
- name
- wday
- type
- number
- optional
- true
-
-
- name
- yday
- type
- number
- optional
- true
-
-
- name
- isdst
- type
- boolean
- optional
- true
-
-
-
- comment
- Date/time table structure used by os.date and os.time
-
-
- classes
-
-
- name
- quaternion
- comment
- Luau Type Definition for LSL UserData Type: quaternion
- properties
-
-
- name
- x
- type
- number
-
-
- name
- y
- type
- number
-
-
- name
- z
- type
- number
-
-
- name
- s
- type
- number
-
-
- methods
-
-
- name
- __add
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- quaternion
-
-
- returnType
- quaternion
-
-
- name
- __sub
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- quaternion
-
-
- returnType
- quaternion
-
-
- name
- __mul
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- quaternion
-
-
- returnType
- quaternion
-
-
- name
- __div
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- quaternion
-
-
- returnType
- quaternion
-
-
- name
- __unm
- parameters
-
-
- name
- self
-
-
- returnType
- quaternion
-
-
- name
- __eq
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- quaternion
-
-
- returnType
- boolean
-
-
- name
- __tostring
- parameters
-
-
- name
- self
-
-
- returnType
- string
-
-
-
-
- name
- uuid
- comment
- Luau Type Definition for LSL UserData Type: uuid
- properties
-
-
- name
- istruthy
- type
- boolean
- comment
- Returns true if the UUID is not the null UUID (all zeros)
-
-
- name
- bytes
- type
- string?
- comment
- Returns the raw 16-byte binary string of the UUID, or nil if the UUID is not in a compressed state
-
-
- methods
-
-
- name
- __tostring
- parameters
-
-
- name
- self
-
-
- returnType
- string
-
-
-
-
- name
- vector
- comment
- Luau Type Definition for LSL UserData Type: vector
- properties
-
-
- name
- x
- type
- number
-
-
- name
- y
- type
- number
-
-
- name
- z
- type
- number
-
-
- methods
-
-
- name
- __add
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- vector
-
-
- returnType
- vector
- comment
- Native component-wise addition
-
-
- name
- __sub
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- vector
-
-
- returnType
- vector
- comment
- Native component-wise subtraction
-
-
- name
- __unm
- parameters
-
-
- name
- self
-
-
- returnType
- vector
- comment
- Unary negation
-
-
- name
- __mul
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- number | vector | quaternion
-
-
- returnType
- vector
- comment
- Multiplication: vector * number or vector * vector -> vector, vector * quaternion -> vector (Rotation)
-
-
- name
- __div
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- number | vector | quaternion
-
-
- returnType
- vector
- comment
- Division: vector / number or vector / vector -> vector (Scale), vector / quaternion -> vector (Rotation by inverse)
-
-
- name
- __mod
- parameters
-
-
- name
- self
-
-
- name
- other
- type
- vector
-
-
- returnType
- vector
- comment
- LSL-style modulo: vector % vector -> vector (Cross Product)
-
-
- name
- __tostring
- parameters
-
-
- name
- self
-
-
- returnType
- string
-
-
-
-
- name
- LLDetectedEvent
- comment
- Event detection class providing access to detected object/avatar information
- properties
-
-
- name
- index
- type
- number
-
-
- name
- valid
- type
- boolean
-
-
- name
- canAdjustDamage
- type
- boolean
-
-
- methods
-
-
-
- name
- LLEvents
- comment
- Event registration and management class for Second Life events
- methods
-
-
- name
- on
- parameters
-
-
- name
- self
-
-
- name
- event
- type
- LLEventName
-
-
- name
- callback
- type
- LLEventHandler
-
-
- returnType
- LLEventHandler
- comment
- Registers a callback for an event. Returns the callback.
-
-
- name
- off
- parameters
-
-
- name
- self
-
-
- name
- event
- type
- LLEventName
-
-
- name
- callback
- type
- LLEventHandler
-
-
- returnType
- boolean
- comment
- Unregisters a callback. Returns true if found and removed.
-
-
- name
- once
- parameters
-
-
- name
- self
-
-
- name
- event
- type
- LLEventName
-
-
- name
- callback
- type
- LLEventHandler
-
-
- returnType
- LLEventHandler
- comment
- Registers a one-time callback. Returns the wrapper function.
-
-
- name
- listeners
- parameters
-
-
- name
- self
-
-
- name
- event
- type
- LLEventName
-
-
- returnType
- {LLEventHandler}
- comment
- Returns a list of all listeners for a specific event.
-
-
- name
- eventNames
- parameters
-
-
- name
- self
-
-
- returnType
- {string}
- comment
- Returns a list of all event names that have listeners.
-
-
-
-
- name
- LLTimers
- comment
- Timer management class for scheduling periodic and one-time callbacks
- methods
-
-
- name
- every
- parameters
-
-
- name
- self
-
-
- name
- seconds
- type
- number
-
-
- name
- callback
- type
- LLTimerEveryCallback
-
-
- returnType
- LLTimerCallback
- comment
- Registers a callback to be called every N seconds. Returns the callback.
-
-
- name
- once
- parameters
-
-
- name
- self
-
-
- name
- seconds
- type
- number
-
-
- name
- callback
- type
- LLTimerOnceCallback
-
-
- returnType
- LLTimerCallback
- comment
- Registers a callback to be called once after N seconds. Returns the callback.
-
-
- name
- off
- parameters
-
-
- name
- self
-
-
- name
- callback
- type
- LLTimerCallback
-
-
- returnType
- boolean
- comment
- Unregisters a timer callback. Returns true if found and removed.
-
-
-
-
- globalVariables
-
-
- name
- quaternion
- type
-
- kind
- callable-table
- tableType
-
- properties
-
-
- name
- create
- type
-
- kind
- function
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- y
- type
- number
-
-
- name
- z
- type
- number
-
-
- name
- s
- type
- number
-
-
- returnType
- quaternion
-
- comment
- Constructor
-
-
- name
- identity
- type
- quaternion
- comment
- Identity quaternion constant
-
-
- name
- normalize
- type
-
- kind
- function
- parameters
-
-
- name
- q
- type
- quaternion
-
-
- returnType
- quaternion
-
- comment
- Returns normalized quaternion
-
-
- name
- magnitude
- type
-
- kind
- function
- parameters
-
-
- name
- q
- type
- quaternion
-
-
- returnType
- number
-
- comment
- Returns magnitude of quaternion
-
-
- name
- dot
- type
-
- kind
- function
- parameters
-
-
- name
- a
- type
- quaternion
-
-
- name
- b
- type
- quaternion
-
-
- returnType
- number
-
- comment
- Dot product of two quaternions
-
-
- name
- slerp
- type
-
- kind
- function
- parameters
-
-
- name
- a
- type
- quaternion
-
-
- name
- b
- type
- quaternion
-
-
- name
- t
- type
- number
-
-
- returnType
- quaternion
-
- comment
- Spherical linear interpolation
-
-
- name
- conjugate
- type
-
- kind
- function
- parameters
-
-
- name
- q
- type
- quaternion
-
-
- returnType
- quaternion
-
- comment
- Returns conjugate of quaternion
-
-
- name
- tofwd
- type
-
- kind
- function
- parameters
-
-
- name
- q
- type
- quaternion
-
-
- returnType
- vector
-
- comment
- Returns forward vector from quaternion rotation
-
-
- name
- toleft
- type
-
- kind
- function
- parameters
-
-
- name
- q
- type
- quaternion
-
-
- returnType
- vector
-
- comment
- Returns left vector from quaternion rotation
-
-
- name
- toup
- type
-
- kind
- function
- parameters
-
-
- name
- q
- type
- quaternion
-
-
- returnType
- vector
-
- comment
- Returns up vector from quaternion rotation
-
-
-
- callSignature
-
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- y
- type
- number
-
-
- name
- z
- type
- number
-
-
- name
- s
- type
- number
-
-
- returnType
- quaternion
-
-
- comment
- Global 'quaternion' library table with callable metatable
-
-
- name
- rotation
- type
-
- kind
- typeof
- target
- quaternion
-
- comment
- 'rotation' global is an alias to the 'quaternion' library
-
-
- name
- uuid
- type
-
- kind
- callable-table
- tableType
-
- properties
-
-
- name
- create
- type
-
- kind
- function
- parameters
-
-
- name
- value
- type
-
- kind
- union
- types
-
- string
- buffer
- uuid
-
-
-
-
- returnType
- uuid?
-
- comment
- Creates a new uuid from a string, buffer, or existing uuid
-
-
-
- callSignature
-
- parameters
-
-
- name
- value
- type
-
- kind
- union
- types
-
- string
- buffer
- uuid
-
-
-
-
- returnType
- uuid?
-
-
- comment
- Global 'uuid' library table
-
-
- name
- vector
- type
-
- kind
- callable-table
- tableType
-
- properties
-
-
- name
- create
- type
-
- kind
- function
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- y
- type
- number
-
-
- name
- z
- type
- number
- optional
- true
-
-
- returnType
- vector
-
- comment
- Creates a new vector with the given component values
-
-
- name
- magnitude
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- returnType
- number
-
- comment
- Calculates the magnitude of a given vector
-
-
- name
- normalize
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- returnType
- vector
-
- comment
- Computes the normalized version (unit vector) of a given vector
-
-
- name
- cross
- type
-
- kind
- function
- parameters
-
-
- name
- a
- type
- vector
-
-
- name
- b
- type
- vector
-
-
- returnType
- vector
-
- comment
- Computes the cross product of two vectors
-
-
- name
- dot
- type
-
- kind
- function
- parameters
-
-
- name
- a
- type
- vector
-
-
- name
- b
- type
- vector
-
-
- returnType
- number
-
- comment
- Computes the dot product of two vectors
-
-
- name
- angle
- type
-
- kind
- function
- parameters
-
-
- name
- a
- type
- vector
-
-
- name
- b
- type
- vector
-
-
- name
- axis
- type
- vector
- optional
- true
-
-
- returnType
- number
-
- comment
- Computes the angle between two vectors in radians
-
-
- name
- floor
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- returnType
- vector
-
- comment
- Applies math.floor to every component of the input vector
-
-
- name
- ceil
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- returnType
- vector
-
- comment
- Applies math.ceil to every component of the input vector
-
-
- name
- abs
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- returnType
- vector
-
- comment
- Applies math.abs to every component of the input vector
-
-
- name
- sign
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- returnType
- vector
-
- comment
- Applies math.sign to every component of the input vector
-
-
- name
- clamp
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- name
- min
- type
- vector
-
-
- name
- max
- type
- vector
-
-
- returnType
- vector
-
- comment
- Applies math.clamp to every component of the input vector
-
-
- name
- max
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- type
- vector
- variadic
- true
-
-
- returnType
- vector
-
- comment
- Applies math.max to the corresponding components of the input vectors
-
-
- name
- min
- type
-
- kind
- function
- parameters
-
-
- name
- v
- type
- vector
-
-
- type
- vector
- variadic
- true
-
-
- returnType
- vector
-
- comment
- Applies math.min to the corresponding components of the input vectors
-
-
- name
- lerp
- type
-
- kind
- function
- parameters
-
-
- name
- a
- type
- vector
-
-
- name
- b
- type
- vector
-
-
- name
- t
- type
- number
-
-
- returnType
- vector
-
- comment
- Linear interpolation between two vectors
-
-
- name
- zero
- type
- vector
- comment
- A zero vector <0,0,0>
-
-
- name
- one
- type
- vector
- comment
- A one vector <1,1,1>
-
-
-
- callSignature
-
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- y
- type
- number
-
-
- name
- z
- type
- number
- optional
- true
-
-
- returnType
- vector
-
-
- comment
- Global 'vector' library table
-
-
- name
- LLEvents
- type
- LLEvents
- comment
- Second Life event management and registration
-
-
- name
- LLTimers
- type
- LLTimers
- comment
- Second Life timer management and scheduling
-
-
- name
- loadstring
- type
- nil
- comment
- loadstring is removed in SLua
-
-
- name
- getfenv
- type
- nil
- comment
- getfenv is removed in SLua
-
-
- name
- setfenv
- type
- nil
- comment
- setfenv is removed in SLua
-
-
- modules
-
-
- name
- bit32
- comment
- Bitwise operations library
- functions
-
-
- name
- arshift
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- disp
- type
- number
-
-
- returnType
- number
- comment
- Arithmetic right shift
-
-
- name
- band
- parameters
-
-
- type
- number
- variadic
- true
-
-
- returnType
- number
- comment
- Bitwise AND of all arguments
-
-
- name
- bnot
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Bitwise NOT
-
-
- name
- bor
- parameters
-
-
- type
- number
- variadic
- true
-
-
- returnType
- number
- comment
- Bitwise OR of all arguments
-
-
- name
- bxor
- parameters
-
-
- type
- number
- variadic
- true
-
-
- returnType
- number
- comment
- Bitwise XOR of all arguments
-
-
- name
- btest
- parameters
-
-
- type
- number
- variadic
- true
-
-
- returnType
- boolean
- comment
- Returns true if bitwise AND of all arguments is not zero
-
-
- name
- extract
- parameters
-
-
- name
- n
- type
- number
-
-
- name
- field
- type
- number
-
-
- name
- width
- type
- number
- optional
- true
-
-
- returnType
- number
- comment
- Extracts bits from n at position field with width
-
-
- name
- lrotate
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- disp
- type
- number
-
-
- returnType
- number
- comment
- Left rotate
-
-
- name
- lshift
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- disp
- type
- number
-
-
- returnType
- number
- comment
- Left shift
-
-
- name
- replace
- parameters
-
-
- name
- n
- type
- number
-
-
- name
- v
- type
- number
-
-
- name
- field
- type
- number
-
-
- name
- width
- type
- number
- optional
- true
-
-
- returnType
- number
- comment
- Replaces bits in n at position field with width using value v
-
-
- name
- rrotate
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- disp
- type
- number
-
-
- returnType
- number
- comment
- Right rotate
-
-
- name
- rshift
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- disp
- type
- number
-
-
- returnType
- number
- comment
- Right shift
-
-
- name
- countlz
- parameters
-
-
- name
- n
- type
- number
-
-
- returnType
- number
- comment
- Count leading zeros
-
-
- name
- countrz
- parameters
-
-
- name
- n
- type
- number
-
-
- returnType
- number
- comment
- Count trailing zeros
-
-
- name
- byteswap
- parameters
-
-
- name
- n
- type
- number
-
-
- returnType
- number
- comment
- Swap byte order
-
-
-
-
- name
- buffer
- comment
- Buffer manipulation library for binary data
- functions
-
-
- name
- create
- parameters
-
-
- name
- size
- type
- number
-
-
- returnType
- buffer
- comment
- Creates a new buffer of the specified size
-
-
- name
- fromstring
- parameters
-
-
- name
- str
- type
- string
-
-
- returnType
- buffer
- comment
- Creates a buffer from a string
-
-
- name
- tostring
- parameters
-
-
- name
- b
- type
- buffer
-
-
- returnType
- string
- comment
- Converts buffer to string
-
-
- name
- readi8
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- returnType
- number
- comment
- Read signed 8-bit integer
-
-
- name
- readu8
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- returnType
- number
- comment
- Read unsigned 8-bit integer
-
-
- name
- readi16
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- returnType
- number
- comment
- Read signed 16-bit integer
-
-
- name
- readu16
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- returnType
- number
- comment
- Read unsigned 16-bit integer
-
-
- name
- readi32
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- returnType
- number
- comment
- Read signed 32-bit integer
-
-
- name
- readu32
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- returnType
- number
- comment
- Read unsigned 32-bit integer
-
-
- name
- readf32
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- returnType
- number
- comment
- Read 32-bit float
-
-
- name
- readf64
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- returnType
- number
- comment
- Read 64-bit float
-
-
- name
- writei8
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write signed 8-bit integer
-
-
- name
- writeu8
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write unsigned 8-bit integer
-
-
- name
- writei16
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write signed 16-bit integer
-
-
- name
- writeu16
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write unsigned 16-bit integer
-
-
- name
- writei32
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write signed 32-bit integer
-
-
- name
- writeu32
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write unsigned 32-bit integer
-
-
- name
- writef32
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write 32-bit float
-
-
- name
- writef64
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write 64-bit float
-
-
- name
- readstring
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- count
- type
- number
-
-
- returnType
- string
- comment
- Read string from buffer
-
-
- name
- writestring
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- string
-
-
- name
- count
- type
- number
- optional
- true
-
-
- returnType
- ()
- comment
- Write string to buffer
-
-
- name
- len
- parameters
-
-
- name
- b
- type
- buffer
-
-
- returnType
- number
- comment
- Returns the length of the buffer
-
-
- name
- copy
- parameters
-
-
- name
- target
- type
- buffer
-
-
- name
- targetOffset
- type
- number
-
-
- name
- source
- type
- buffer
-
-
- name
- sourceOffset
- type
- number
- optional
- true
-
-
- name
- count
- type
- number
- optional
- true
-
-
- returnType
- ()
- comment
- Copy data from source buffer to target buffer
-
-
- name
- fill
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- offset
- type
- number
-
-
- name
- value
- type
- number
-
-
- name
- count
- type
- number
- optional
- true
-
-
- returnType
- ()
- comment
- Fill buffer with a value
-
-
- name
- readbits
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- bitOffset
- type
- number
-
-
- name
- bitCount
- type
- number
-
-
- returnType
- number
- comment
- Read bits from buffer
-
-
- name
- writebits
- parameters
-
-
- name
- b
- type
- buffer
-
-
- name
- bitOffset
- type
- number
-
-
- name
- bitCount
- type
- number
-
-
- name
- value
- type
- number
-
-
- returnType
- ()
- comment
- Write bits to buffer
-
-
-
-
- name
- coroutine
- comment
- Coroutine manipulation library
- functions
-
-
- name
- create
- parameters
-
-
- name
- f
- type
- (...any) -> ...any
-
-
- returnType
- thread
- comment
- Creates a new coroutine from a function
-
-
- name
- resume
- parameters
-
-
- name
- co
- type
- thread
-
-
- type
- any
- variadic
- true
-
-
- returnType
- (boolean, ...any)
- comment
- Resumes a coroutine, returns success and results
-
-
- name
- running
- parameters
-
- returnType
- thread?
- comment
- Returns the running coroutine, or nil if called from main thread
-
-
- name
- status
- parameters
-
-
- name
- co
- type
- thread
-
-
- returnType
- "running" | "suspended" | "normal" | "dead"
- comment
- Returns the status of a coroutine
-
-
- name
- wrap
- parameters
-
-
- name
- f
- type
- (...any) -> ...any
-
-
- returnType
- (...any) -> ...any
- comment
- Creates a coroutine and returns a function that resumes it
-
-
- name
- yield
- parameters
-
-
- type
- any
- variadic
- true
-
-
- returnType
- ...any
- comment
- Suspends the coroutine and returns values to resume
-
-
- name
- isyieldable
- parameters
-
- returnType
- boolean
- comment
- Returns true if the coroutine can yield
-
-
- name
- close
- parameters
-
-
- name
- co
- type
- thread
-
-
- returnType
- (boolean, string?)
- comment
- Closes a coroutine, returns success and optional error message
-
-
-
-
- name
- debug
- comment
- Debug library for introspection
- functions
-
-
- name
- info
- parameters
-
-
- name
- thread
- type
- thread
-
-
- name
- level
- type
- number
-
-
- name
- options
- type
- string
-
-
- returnType
- ...any
- comment
- Returns information about a function or stack level
- overloads
-
-
- parameters
-
-
- name
- level
- type
- number
-
-
- name
- options
- type
- string
-
-
- returnType
- ...any
- comment
- Returns information about a stack level
-
-
- parameters
-
-
- name
- func
- type
- (...any) -> ...any
-
-
- name
- options
- type
- string
-
-
- returnType
- ...any
- comment
- Returns information about a function
-
-
-
-
- name
- traceback
- parameters
-
-
- name
- thread
- type
- thread
-
-
- name
- message
- type
- string
- optional
- true
-
-
- name
- level
- type
- number
- optional
- true
-
-
- returnType
- string
- comment
- Returns a string with a traceback of the call stack
- overloads
-
-
- parameters
-
-
- name
- message
- type
- string
- optional
- true
-
-
- name
- level
- type
- number
- optional
- true
-
-
- returnType
- string
- comment
- Returns a string with a traceback of the current call stack
-
-
-
-
-
-
- name
- llbase64
- comment
- Base64 encoding/decoding library
- functions
-
-
- name
- encode
- parameters
-
-
- name
- data
- type
- string | buffer
-
-
- returnType
- string
- comment
- Encodes a string or buffer to base64
-
-
- name
- decode
- parameters
-
-
- name
- data
- type
- string
-
-
- returnType
- string
- comment
- Decodes a base64 string to a string
- overloads
-
-
- parameters
-
-
- name
- data
- type
- string
-
-
- name
- asBuffer
- type
- boolean
- optional
- true
-
-
- returnType
- string | buffer
- comment
- Decodes a base64 string to a string or buffer
-
-
-
-
-
-
- name
- lljson
- comment
- JSON encoding/decoding library for Second Life
- properties
-
-
- name
- null
- type
- any
- comment
- A constant to pass for null to json encode
-
-
- name
- empty_array_mt
- type
- { [any]: any }
- comment
- Metatable for declaring table as an empty array for json encode
-
-
- name
- array_mt
- type
- { [any]: any }
- comment
- Metatable for declaring table as an array for json encode
-
-
- name
- empty_array
- type
- any
- comment
- A constant to pass for an empty array to json encode
-
-
- name
- _NAME
- type
- string
- comment
- Name of the lljson library
-
-
- name
- _VERSION
- type
- string
- comment
- Version of the lljson library
-
-
- functions
-
-
- name
- encode
- parameters
-
-
- name
- value
- type
- any
-
-
- returnType
- string
- comment
- Encodes a Lua value as JSON
-
-
- name
- decode
- parameters
-
-
- name
- json
- type
- string
-
-
- returnType
- any
- comment
- Decodes a JSON string to a Lua value
-
-
- name
- slencode
- parameters
-
-
- name
- value
- type
- any
-
-
- name
- tight
- type
- boolean
- optional
- true
-
-
- returnType
- string
- comment
- Encodes a Lua value as JSON preserving SL types. Use tight to encode more compactly.
-
-
- name
- sldecode
- parameters
-
-
- name
- json
- type
- string
-
-
- returnType
- any
- comment
- Decodes a JSON string to a Lua value preserving SL types
-
-
-
-
- name
- math
- comment
- Mathematical functions library
- properties
-
-
- name
- pi
- type
- number
- comment
- The value of pi
-
-
- name
- huge
- type
- number
- comment
- A value larger than any other numeric value (infinity)
-
-
- functions
-
-
- name
- abs
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the absolute value of x
-
-
- name
- acos
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the arc cosine of x (in radians)
-
-
- name
- asin
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the arc sine of x (in radians)
-
-
- name
- atan
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the arc tangent of x (in radians)
-
-
- name
- atan2
- parameters
-
-
- name
- y
- type
- number
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the arc tangent of y/x (in radians), using the signs to determine the quadrant
-
-
- name
- ceil
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the smallest integer larger than or equal to x
-
-
- name
- clamp
- parameters
-
-
- name
- n
- type
- number
-
-
- name
- min
- type
- number
-
-
- name
- max
- type
- number
-
-
- returnType
- number
- comment
- Returns n clamped between min and max
-
-
- name
- cos
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the cosine of x (x in radians)
-
-
- name
- cosh
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the hyperbolic cosine of x
-
-
- name
- deg
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Converts x from radians to degrees
-
-
- name
- exp
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns e^x
-
-
- name
- floor
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the largest integer smaller than or equal to x
-
-
- name
- fmod
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- y
- type
- number
-
-
- returnType
- number
- comment
- Returns the remainder of x/y that rounds towards zero
-
-
- name
- frexp
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- (number, number)
- comment
- Returns m and e such that x = m * 2^e
-
-
- name
- ldexp
- parameters
-
-
- name
- m
- type
- number
-
-
- name
- e
- type
- number
-
-
- returnType
- number
- comment
- Returns m * 2^e
-
-
- name
- lerp
- parameters
-
-
- name
- a
- type
- number
-
-
- name
- b
- type
- number
-
-
- name
- t
- type
- number
-
-
- returnType
- number
- comment
- Linear interpolation between a and b by t
-
-
- name
- log
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- base
- type
- number
- optional
- true
-
-
- returnType
- number
- comment
- Returns the logarithm of x in the given base (default e)
-
-
- name
- log10
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the base-10 logarithm of x
-
-
- name
- map
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- inMin
- type
- number
-
-
- name
- inMax
- type
- number
-
-
- name
- outMin
- type
- number
-
-
- name
- outMax
- type
- number
-
-
- returnType
- number
- comment
- Maps x from input range to output range
-
-
- name
- max
- parameters
-
-
- name
- x
- type
- number
-
-
- type
- number
- variadic
- true
-
-
- returnType
- number
- comment
- Returns the maximum value among the arguments
-
-
- name
- min
- parameters
-
-
- name
- x
- type
- number
-
-
- type
- number
- variadic
- true
-
-
- returnType
- number
- comment
- Returns the minimum value among the arguments
-
-
- name
- modf
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- (number, number)
- comment
- Returns the integer and fractional parts of x
-
-
- name
- noise
- parameters
-
-
- name
- x
- type
- number
-
-
- name
- y
- type
- number
- optional
- true
-
-
- name
- z
- type
- number
- optional
- true
-
-
- returnType
- number
- comment
- Returns Perlin noise value for the given coordinates
-
-
- name
- pow
- parameters
-
-
- name
- base
- type
- number
-
-
- name
- exponent
- type
- number
-
-
- returnType
- number
- comment
- Returns base^exponent
-
-
- name
- rad
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Converts x from degrees to radians
-
-
- name
- random
- parameters
-
-
- name
- m
- type
- number
- optional
- true
-
-
- name
- n
- type
- number
- optional
- true
-
-
- returnType
- number
- comment
- Returns a pseudo-random number
-
-
- name
- randomseed
- parameters
-
-
- name
- seed
- type
- number
-
-
- returnType
- ()
- comment
- Sets the seed for the pseudo-random generator
-
-
- name
- round
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns x rounded to the nearest integer
-
-
- name
- sign
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns -1, 0, or 1 depending on the sign of x
-
-
- name
- sin
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the sine of x (x in radians)
-
-
- name
- sinh
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the hyperbolic sine of x
-
-
- name
- sqrt
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the square root of x
-
-
- name
- tan
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the tangent of x (x in radians)
-
-
- name
- tanh
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- number
- comment
- Returns the hyperbolic tangent of x
-
-
- name
- isnan
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- boolean
- comment
- Returns true if x is NaN
-
-
- name
- isinf
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- boolean
- comment
- Returns true if x is infinite
-
-
- name
- isfinite
- parameters
-
-
- name
- x
- type
- number
-
-
- returnType
- boolean
- comment
- Returns true if x is finite
-
-
-
-
- name
- os
- comment
- Operating system facilities library
- functions
-
-
- name
- clock
- parameters
-
- returnType
- number
- comment
- Returns CPU time used by the program in seconds
-
-
- name
- date
- parameters
-
-
- name
- format
- type
- string
- optional
- true
-
-
- name
- time
- type
- number
- optional
- true
-
-
- returnType
- string | OsDateTime | nil
- comment
- Returns a string or table containing date and time
-
-
- name
- difftime
- parameters
-
-
- name
- t2
- type
- number
-
-
- name
- t1
- type
- number
- optional
- true
-
-
- returnType
- number
- comment
- Returns the difference in seconds between two times
-
-
- name
- time
- parameters
-
-
- name
- time
- type
- OsDateTime
- optional
- true
-
-
- returnType
- number?
- comment
- Returns the current time or converts a table to time
-
-
-
-
- name
- string
- comment
- String manipulation library
- functions
-
-
- name
- byte
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- i
- type
- number
- optional
- true
-
-
- name
- j
- type
- number
- optional
- true
-
-
- returnType
- ...number
- comment
- Returns the internal numeric codes of the characters
-
-
- name
- char
- parameters
-
-
- type
- number
- variadic
- true
-
-
- returnType
- string
- comment
- Returns a string from character codes
-
-
- name
- find
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- pattern
- type
- string
-
-
- name
- init
- type
- number
- optional
- true
-
-
- name
- plain
- type
- boolean
- optional
- true
-
-
- returnType
- (number?, number?, ...string)
- comment
- Finds first match of pattern in string
-
-
- name
- format
- parameters
-
-
- name
- formatstring
- type
- string
-
-
- type
- any
- variadic
- true
-
-
- returnType
- string
- comment
- Returns a formatted string
-
-
- name
- gmatch
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- pattern
- type
- string
-
-
- returnType
- () -> ...string
- comment
- Returns an iterator function for pattern matches
-
-
- name
- gsub
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- pattern
- type
- string
-
-
- name
- repl
- type
- string | { [string]: string } | (...string) -> string
-
-
- name
- n
- type
- number
- optional
- true
-
-
- returnType
- (string, number)
- comment
- Global substitution of pattern matches
-
-
- name
- len
- parameters
-
-
- name
- s
- type
- string
-
-
- returnType
- number
- comment
- Returns the length of the string
-
-
- name
- lower
- parameters
-
-
- name
- s
- type
- string
-
-
- returnType
- string
- comment
- Converts string to lowercase
-
-
- name
- match
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- pattern
- type
- string
-
-
- name
- init
- type
- number
- optional
- true
-
-
- returnType
- ...string
- comment
- Returns captures from pattern match
-
-
- name
- pack
- parameters
-
-
- name
- fmt
- type
- string
-
-
- type
- any
- variadic
- true
-
-
- returnType
- string
- comment
- Packs values into a binary string
-
-
- name
- packsize
- parameters
-
-
- name
- fmt
- type
- string
-
-
- returnType
- number
- comment
- Returns the size of a packed string for the given format
-
-
- name
- rep
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- n
- type
- number
-
-
- returnType
- string
- comment
- Returns a string repeated n times
-
-
- name
- reverse
- parameters
-
-
- name
- s
- type
- string
-
-
- returnType
- string
- comment
- Reverses a string
-
-
- name
- split
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- separator
- type
- string
- optional
- true
-
-
- returnType
- {string}
- comment
- Splits a string by separator
-
-
- name
- sub
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- i
- type
- number
-
-
- name
- j
- type
- number
- optional
- true
-
-
- returnType
- string
- comment
- Returns a substring
-
-
- name
- unpack
- parameters
-
-
- name
- fmt
- type
- string
-
-
- name
- s
- type
- string
-
-
- name
- pos
- type
- number
- optional
- true
-
-
- returnType
- ...any
- comment
- Unpacks values from a binary string
-
-
- name
- upper
- parameters
-
-
- name
- s
- type
- string
-
-
- returnType
- string
- comment
- Converts string to uppercase
-
-
-
-
- name
- table
- comment
- Table manipulation library
- functions
-
-
- name
- concat
- parameters
-
-
- name
- list
- type
- {string}
-
-
- name
- sep
- type
- string
- optional
- true
-
-
- name
- i
- type
- number
- optional
- true
-
-
- name
- j
- type
- number
- optional
- true
-
-
- returnType
- string
- comment
- Concatenates table elements into a string
-
-
- name
- foreach
- parameters
-
-
- name
- t
- type
- {[any]: any}
-
-
- name
- f
- type
- (key: any, value: any) -> any
-
-
- returnType
- any?
- comment
- Iterates over table key-value pairs (deprecated)
-
-
- name
- foreachi
- parameters
-
-
- name
- t
- type
- {any}
-
-
- name
- f
- type
- (index: number, value: any) -> any
-
-
- returnType
- any?
- comment
- Iterates over array indices (deprecated)
-
-
- name
- getn
- parameters
-
-
- name
- t
- type
- {any}
-
-
- returnType
- number
- comment
- Returns the length of a table (deprecated, use # operator)
-
-
- name
- maxn
- parameters
-
-
- name
- t
- type
- {any}
-
-
- returnType
- number
- comment
- Returns the largest positive numeric index
-
-
- name
- insert
- parameters
-
-
- name
- list
- type
- {any}
-
-
- name
- value
- type
- any
-
-
- returnType
- ()
- comment
- Inserts an element at the end of a list
- overloads
-
-
- parameters
-
-
- name
- list
- type
- {any}
-
-
- name
- pos
- type
- number
-
-
- name
- value
- type
- any
-
-
- returnType
- ()
- comment
- Inserts an element at a specific position
-
-
-
-
- name
- remove
- parameters
-
-
- name
- list
- type
- {any}
-
-
- name
- pos
- type
- number
- optional
- true
-
-
- returnType
- any?
- comment
- Removes and returns an element from a list
-
-
- name
- sort
- parameters
-
-
- name
- list
- type
- {any}
-
-
- name
- comp
- type
- (a: any, b: any) -> boolean
- optional
- true
-
-
- returnType
- ()
- comment
- Sorts list elements in place
-
-
- name
- pack
- parameters
-
-
- type
- any
- variadic
- true
-
-
- returnType
- { n: number, [number]: any }
- comment
- Packs arguments into a table with length field n
-
-
- name
- unpack
- parameters
-
-
- name
- list
- type
- {any}
-
-
- name
- i
- type
- number
- optional
- true
-
-
- name
- j
- type
- number
- optional
- true
-
-
- returnType
- ...any
- comment
- Unpacks table elements as multiple return values
-
-
- name
- move
- parameters
-
-
- name
- a1
- type
- {any}
-
-
- name
- f
- type
- number
-
-
- name
- e
- type
- number
-
-
- name
- t
- type
- number
-
-
- name
- a2
- type
- {any}
- optional
- true
-
-
- returnType
- {any}
- comment
- Moves elements from one table to another
-
-
- name
- create
- parameters
-
-
- name
- count
- type
- number
-
-
- name
- value
- type
- any
- optional
- true
-
-
- returnType
- {any}
- comment
- Creates a new table with pre-allocated array slots
-
-
- name
- find
- parameters
-
-
- name
- t
- type
- {any}
-
-
- name
- value
- type
- any
-
-
- name
- init
- type
- number
- optional
- true
-
-
- returnType
- number?
- comment
- Finds the index of a value in an array
-
-
- name
- clear
- parameters
-
-
- name
- t
- type
- {[any]: any}
-
-
- returnType
- ()
- comment
- Removes all elements from a table
-
-
- name
- freeze
- parameters
-
-
- name
- t
- type
- {[any]: any}
-
-
- returnType
- {[any]: any}
- comment
- Makes a table read-only
-
-
- name
- isfrozen
- parameters
-
-
- name
- t
- type
- {[any]: any}
-
-
- returnType
- boolean
- comment
- Returns true if a table is frozen
-
-
- name
- clone
- parameters
-
-
- name
- t
- type
- {[any]: any}
-
-
- returnType
- {[any]: any}
- comment
- Creates a shallow copy of a table
-
-
-
-
- name
- utf8
- comment
- UTF-8 support library
- properties
-
-
- name
- charpattern
- type
- string
- comment
- Pattern that matches exactly one UTF-8 byte sequence
-
-
- functions
-
-
- name
- char
- parameters
-
-
- type
- number
- variadic
- true
-
-
- returnType
- string
- comment
- Returns a string from UTF-8 codepoints
-
-
- name
- codes
- parameters
-
-
- name
- s
- type
- string
-
-
- returnType
- ((string, number) -> (number, number), string, number)
- comment
- Returns an iterator for UTF-8 codepoints in a string
-
-
- name
- codepoint
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- i
- type
- number
- optional
- true
-
-
- name
- j
- type
- number
- optional
- true
-
-
- returnType
- ...number
- comment
- Returns the codepoints of characters in a string
-
-
- name
- len
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- i
- type
- number
- optional
- true
-
-
- name
- j
- type
- number
- optional
- true
-
-
- returnType
- (number?, number?)
- comment
- Returns the number of UTF-8 characters in a string, or nil and error position
-
-
- name
- offset
- parameters
-
-
- name
- s
- type
- string
-
-
- name
- n
- type
- number
-
-
- name
- i
- type
- number
- optional
- true
-
-
- returnType
- number?
- comment
- Returns the byte position of the n-th character
-
-
-
-
- globalFunctions
-
-
- name
- dangerouslyexecuterequiredmodule
- parameters
-
-
- name
- f
- type
- (...any) -> ...any
-
-
- returnType
- ...any
- comment
- Dangerously executes a required module function
-
-
- name
- touuid
- parameters
-
-
- name
- val
- type
- string | buffer | uuid
-
-
- returnType
- uuid?
- comment
- Converts a string, buffer, or uuid to a uuid, returns nil if invalid
-
-
- name
- tovector
- parameters
-
-
- name
- val
- type
- any
-
-
- returnType
- vector?
- comment
- Converts a value to a vector, returns nil if invalid
-
-
- name
- toquaternion
- parameters
-
-
- name
- val
- type
- any
-
-
- returnType
- quaternion?
- comment
- Converts a value to a quaternion, returns nil if invalid
-
-
- name
- torotation
- parameters
-
-
- name
- val
- type
- any
-
-
- returnType
- quaternion?
- comment
- Converts a value to a rotation (quaternion), returns nil if invalid
-
-
- constants
-
-
-
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index a9e3afbc58..544473ba77 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -507,11 +507,10 @@ bool LLScriptEdCore::postBuild()
initMenu();
- mSyntaxIDConnection = LLSyntaxIdLSL::getInstance()->addSyntaxIDCallback(boost::bind(&LLScriptEdCore::processKeywords, this));
+ mSyntaxIDConnection = LLSyntaxDefCache::getInstance()->addSyntaxIDCallback(boost::bind(&LLScriptEdCore::processKeywords, this));
// Intialise keyword highlighting for the current simulator's version of LSL
- LLSyntaxIdLSL::getInstance()->initialize();
- LLSyntaxLua::getInstance()->initialize();
+ LLSyntaxDefCache::getInstance();
processKeywords();
mCommitCallbackRegistrar.add("FontSize.Set", boost::bind(&LLScriptEdCore::onChangeFontSize, this, _2));
diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp
index 2a4c2b9d0b..ac6b81f677 100644
--- a/indra/newview/llscripteditor.cpp
+++ b/indra/newview/llscripteditor.cpp
@@ -342,8 +342,8 @@ void LLScriptEditor::drawLineNumbers()
void LLScriptEditor::initKeywords(bool luau_language)
{
- mKeywordsLua.initialize(LLSyntaxLua::getInstance()->getKeywordsXML(), true);
- mKeywordsLSL.initialize(LLSyntaxIdLSL::getInstance()->getKeywordsXML(), false);
+ mKeywordsLua.initialize(LLSyntaxDefCache::getInstance()->getLuaKeywords(), true);
+ mKeywordsLSL.initialize(LLSyntaxDefCache::getInstance()->getLSLKeywords(), false);
mLuauLanguage = luau_language;
diff --git a/indra/newview/llscripteditorws.cpp b/indra/newview/llscripteditorws.cpp
index 30a1ca53f6..3ca9be44bc 100644
--- a/indra/newview/llscripteditorws.cpp
+++ b/indra/newview/llscripteditorws.cpp
@@ -2,6 +2,9 @@
* @file llscripteditorws.cpp
* @brief JSON-RPC 2.0 WebSocket server implementation for external script editor integration
*
+ * For a full description of the JSON-RPC protocol and all supported methods,
+ * see doc/external-editor-json-rpc.md in the repository root.
+ *
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2025, Linden Research, Inc.
@@ -73,7 +76,7 @@ LLWebsocketMgr::WSConnection::ptr_t LLScriptEditorWSServer::connectionFactory(LL
void LLScriptEditorWSServer::onStarted()
{
- LLSyntaxIdLSL& syntax_id_mgr = LLSyntaxIdLSL::instance();
+ LLSyntaxDefCache& syntax_id_mgr = LLSyntaxDefCache::instance();
wptr_t that(std::static_pointer_cast(shared_from_this()));
mLastSyntaxId = syntax_id_mgr.getSyntaxID();
@@ -272,6 +275,26 @@ void LLScriptEditorWSServer::setupConnectionMethods(LLJSONRPCConnection::ptr_t c
}
return LLSD();
});
+ script_connection->registerMethod("language.syntax.cache",
+ [that](const std::string&, const LLSD&, const LLSD& params)
+ {
+ auto server = that.lock();
+ if (server)
+ {
+ return server->handleSyntaxCacheRequest();
+ }
+ return LLSD();
+ });
+ script_connection->registerMethod("language.syntax.get",
+ [that](const std::string&, const LLSD&, const LLSD& params)
+ {
+ auto server = that.lock();
+ if (server)
+ {
+ return server->handleSyntaxCacheFileRequest(params);
+ }
+ return LLSD();
+ });
script_connection->registerMethod("script.subscribe",
[that, connection_id](const std::string&, const LLSD&, const LLSD& params) -> LLSD
{
@@ -302,7 +325,7 @@ void LLScriptEditorWSServer::setupConnectionMethods(LLJSONRPCConnection::ptr_t c
void LLScriptEditorWSServer::broadcastLanguageChange()
{
- LLUUID syntax_id = LLSyntaxIdLSL::instance().getSyntaxID();
+ LLUUID syntax_id = LLSyntaxDefCache::instance().getSyntaxID();
if (syntax_id != mLastSyntaxId)
{
@@ -340,12 +363,12 @@ LLSD LLScriptEditorWSServer::handleSyntaxRequest(const LLSD& params) const
response["id"] = mLastSyntaxId;
if (category == "defs.lua")
{
- response["defs"] = LLSyntaxLua::instance().getTypesXML();
+ response["defs"] = LLSyntaxDefCache::instance().getLuaKeywords();
response["success"] = response["defs"].isDefined();
}
else if (category == "defs.lsl")
{
- response["defs"] = LLSyntaxIdLSL::instance().getKeywordsXML();
+ response["defs"] = LLSyntaxDefCache::instance().getLSLKeywords();
response["success"] = response["defs"].isDefined();
}
else
@@ -356,6 +379,71 @@ LLSD LLScriptEditorWSServer::handleSyntaxRequest(const LLSD& params) const
return response;
}
+LLSD LLScriptEditorWSServer::handleSyntaxCacheRequest() const
+{
+ LLSD response;
+ // Add array of cached syntax definition files
+ LLSD syntax_files = LLSD::emptyArray();
+ for (const auto& name : LLSyntaxDefCache::instance().getCacheFileNames())
+ {
+ syntax_files.append(name);
+ }
+ response["files"] = syntax_files;
+ response["success"] = true;
+ return response;
+}
+
+LLSD LLScriptEditorWSServer::handleSyntaxCacheFileRequest(const LLSD& params) const
+{
+ std::string filename = params["filename"].asString();
+ bool as_json = params["as_json"].asBoolean();
+
+ LLSyntaxDefCache& cache = LLSyntaxDefCache::instance();
+ LLSD response;
+
+ if (filename.empty())
+ {
+ response["error"] = "No filename specified";
+ response["success"] = false;
+ return response;
+ }
+ if (!cache.hasCacheFile(filename))
+ {
+ response["error"] = "Requested syntax cache file not found";
+ response["success"] = false;
+ return response;
+ }
+ bool success = false;
+ if (as_json)
+ {
+ LLSD file_content = cache.loadCacheFileAsLLSD(filename);
+ if (file_content.isDefined())
+ {
+ response["content"] = file_content;
+ success = true;
+ }
+ else
+ {
+ response["error"] = "Failed to load and format syntax cache file.";
+ }
+ }
+ else
+ {
+ std::string content = cache.loadCacheFile(filename);
+ if (!content.empty())
+ {
+ response["content"] = content;
+ success = true;
+ }
+ else
+ {
+ response["error"] = "Failed to load syntax cache file";
+ }
+ }
+ response["success"] = success;
+ return response;
+}
+
LLSD LLScriptEditorWSServer::handleScriptSubscribe(U32 connection_id, const LLSD& params)
{
LLSD response(LLSD::emptyMap());
@@ -710,12 +798,13 @@ void LLScriptEditorWSConnection::onOpen()
languages.append("lsl");
languages.append("luau");
handshake["languages"] = languages;
- handshake["syntax_id"] = LLSyntaxIdLSL::instance().getSyntaxID();
+ handshake["syntax_id"] = LLSyntaxDefCache::instance().getSyntaxID();
// Features object
LLSD features;
features["live_sync"] = true;
features["compilation"] = true;
+ features["syntax_cache"] = true;
handshake["features"] = features;
wptr_t that = shared_from_this();
diff --git a/indra/newview/llscripteditorws.h b/indra/newview/llscripteditorws.h
index c8898c66a7..765ebe83f2 100644
--- a/indra/newview/llscripteditorws.h
+++ b/indra/newview/llscripteditorws.h
@@ -192,6 +192,8 @@ class LLScriptEditorWSServer : public LLJSONRPCServer
LLSD handleLanguageIdRequest() const;
LLSD handleSyntaxRequest(const LLSD ¶ms) const;
+ LLSD handleSyntaxCacheRequest() const;
+ LLSD handleSyntaxCacheFileRequest(const LLSD& params) const;
LLSD handleScriptSubscribe(U32 connection_id, const LLSD& params);
LLSD handleScriptUnsubscribe(U32 connection_id, const LLSD& params);
LLSD handleFileWatcherFileListRequest() const;
diff --git a/indra/newview/llsyntaxid.cpp b/indra/newview/llsyntaxid.cpp
index 16274f59bc..9c1a0ef403 100644
--- a/indra/newview/llsyntaxid.cpp
+++ b/indra/newview/llsyntaxid.cpp
@@ -35,40 +35,57 @@
#include "llviewerregion.h"
#include "llcorehttputil.h"
+
//-----------------------------------------------------------------------------
// LLSyntaxIdLSL
//-----------------------------------------------------------------------------
-const std::string SYNTAX_ID_CAPABILITY_NAME = "LSLSyntax";
-const std::string SYNTAX_ID_SIMULATOR_FEATURE = "LSLSyntaxId";
-const std::string FILENAME_DEFAULT_LSL = "keywords_lsl_default.xml";
-const std::string FILENAME_DEFAULT_LUA = "keywords_lua_default.xml";
-
-/**
- * @brief LLSyntaxIdLSL constructor
- */
-LLSyntaxIdLSL::LLSyntaxIdLSL()
-: mKeywordsXml(LLSD())
-, mCapabilityURL(std::string())
-, mFilePath(LL_PATH_APP_SETTINGS)
-, mSyntaxId(LLUUID())
-, mInitialized(false)
+namespace
+{
+ const std::string SYNTAX_ID_CAPABILITY_NAME = "LSLSyntax";
+ const std::string SYNTAX_DEF_CAPABILITY_NAME = "ScriptDefinitions";
+ const std::string SYNTAX_ID_SIMULATOR_FEATURE = "LSLSyntaxId";
+ const std::string FILENAME_INTERNAL_LSL = "lsl_keywords.xml";
+ const std::string FILENAME_INTERNAL_LUA = "lua_keywords.xml";
+
+ constexpr U32 LLSD_SYNTAX_LSL_VERSION_EXPECTED = 2;
+ const std::string LLSD_SYNTAX_LSL_VERSION_KEY("llsd-lsl-syntax-version");
+
+ const std::unordered_set MEMCACHED_LLSD = {
+ FILENAME_INTERNAL_LSL,
+ FILENAME_INTERNAL_LUA
+ };
+} // namespace
+
+//========================================================================
+void LLSyntaxDefCache::initSingleton()
{
- loadDefaultKeywordsIntoLLSD();
- mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLSyntaxIdLSL::handleRegionChanged, this));
+ buildDefaultCache();
+ loadKeywordsIntoLLSD();
+ mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLSyntaxDefCache::handleRegionChanged, this));
handleRegionChanged(); // Kick off an initial caps query and fetch
}
-void LLSyntaxIdLSL::buildFullFileSpec()
+void LLSyntaxDefCache::cleanupSingleton()
{
- ELLPath path = mSyntaxId.isNull() ? LL_PATH_APP_SETTINGS : LL_PATH_CACHE;
- const std::string filename = mSyntaxId.isNull() ? FILENAME_DEFAULT_LSL : "keywords_lsl_" + mSyntaxId.asString() + ".llsd.xml";
- mFullFileSpec = gDirUtilp->getExpandedFilename(path, filename);
+ gAgent.removeRegionChangedCallback(mRegionChangedCallback);
+ mLSLKeywords = LLSD();
+ mLuaKeywords = LLSD();
+ mCapabilityURL = std::string();
+ mSyntaxId = LLUUID();
+ mFileCachePaths.clear();
}
-//-----------------------------------------------------------------------------
-// syntaxIdChange()
-//-----------------------------------------------------------------------------
-bool LLSyntaxIdLSL::syntaxIdChanged()
+boost::signals2::connection LLSyntaxDefCache::addSyntaxIDCallback(const syntax_id_changed_signal_t::slot_type& cb)
+{
+ return mSyntaxIDChangedSignal.connect(cb);
+}
+
+//========================================================================
+// checkSyntaxId()
+// Checks the current region for the LSLSyntaxId feature and capability, and
+// if found checks the syntax ID against the one we have. If they differ,
+// updates the syntax ID and returns true. Otherwise returns false.
+bool LLSyntaxDefCache::updateSyntaxId()
{
LLViewerRegion* region = gAgent.getRegion();
@@ -83,51 +100,97 @@ bool LLSyntaxIdLSL::syntaxIdChanged()
{
// get and check the hash
LLUUID new_syntax_id = sim_features[SYNTAX_ID_SIMULATOR_FEATURE].asUUID();
- mCapabilityURL = region->getCapability(SYNTAX_ID_CAPABILITY_NAME);
+
+ // *Note* the syntax ID may not have changed, but the region almost certainly has.
+ // update the cap URL
+ mCapabilityURL = region->getCapability(SYNTAX_DEF_CAPABILITY_NAME);
+ mUseDefsCap = !mCapabilityURL.empty();
+ if (!mUseDefsCap)
+ {
+ mCapabilityURL = region->getCapability(SYNTAX_ID_CAPABILITY_NAME);
+ }
LL_DEBUGS("SyntaxLSL") << SYNTAX_ID_SIMULATOR_FEATURE << " capability URL: " << mCapabilityURL << LL_ENDL;
+
if (new_syntax_id != mSyntaxId)
{
LL_DEBUGS("SyntaxLSL") << "New SyntaxID '" << new_syntax_id << "' found." << LL_ENDL;
mSyntaxId = new_syntax_id;
return true;
}
- else
- LL_DEBUGS("SyntaxLSL") << "SyntaxID matches what we have." << LL_ENDL;
+
+ LL_DEBUGS("SyntaxLSL") << "SyntaxID has not changed. Still " << mSyntaxId << LL_ENDL;
}
}
else
{
- region->setCapabilitiesReceivedCallback(boost::bind(&LLSyntaxIdLSL::handleCapsReceived, this, _1));
+ region->setCapabilitiesReceivedCallback(boost::bind(&LLSyntaxDefCache::handleCapsReceived, this, _1));
LL_DEBUGS("SyntaxLSL") << "Region has not received capabilities. Waiting for caps..." << LL_ENDL;
}
}
return false;
}
+void LLSyntaxDefCache::handleRegionChanged()
+{
+ if (updateSyntaxId())
+ {
+ if (!checkCacheAndLoad(mSyntaxId))
+ {
+ fetchKeywords();
+ }
+ }
+}
+
+void LLSyntaxDefCache::handleCapsReceived(const LLUUID& region_uuid)
+{
+ LLViewerRegion* current_region = gAgent.getRegion();
+
+ if (region_uuid.notNull() && current_region->getRegionID() == region_uuid)
+ {
+ updateSyntaxId();
+ if (!checkCacheAndLoad(mSyntaxId))
+ {
+ fetchKeywords();
+ }
+ }
+}
+
//-----------------------------------------------------------------------------
-// fetchKeywordsFile
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::fetchKeywordsFile(const std::string& filespec)
+// fetchKeywords
+// Initiates a fetch of the current language definitions from the region caps.
+void LLSyntaxDefCache::fetchKeywords()
{
- LLCoros::instance().launch("LLSyntaxIdLSL::fetchKeywordsFileCoro",
- boost::bind(&LLSyntaxIdLSL::fetchKeywordsFileCoro, this, mCapabilityURL, filespec));
- LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId capability URL is: " << mCapabilityURL << ". Filename to use is: '" << filespec << "'." << LL_ENDL;
+ if (mCapabilityURL.empty())
+ {
+ LL_WARNS("SyntaxLSL") << "No capability URL for fetching syntax definitions." << LL_ENDL;
+ return;
+ }
+ if (mUseDefsCap)
+ {
+ LLCoros::instance().launch("LLSyntaxDefCache::fetchKeywordsDefsCoro",
+ boost::bind(&LLSyntaxDefCache::fetchKeywordsDefsCoro, this, mCapabilityURL, mSyntaxId));
+ }
+ else
+ {
+ LLCoros::instance().launch("LLSyntaxDefCache::fetchKeywordsFileCoro",
+ boost::bind(&LLSyntaxDefCache::fetchKeywordsFileCoro, this, mCapabilityURL, mSyntaxId));
+ }
}
//-----------------------------------------------------------------------------
// fetchKeywordsFileCoro
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
+// This uses the legacy language cap which only sends the LSL keywords file.
+void LLSyntaxDefCache::fetchKeywordsFileCoro(std::string url, LLUUID syntax_id)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter = std::make_shared("fetchKeywordsFileCoro", httpPolicy);
LLCore::HttpRequest::ptr_t httpRequest = std::make_shared();
- std::pair::iterator, bool> insrt = mInflightFetches.insert(fileSpec);
+ auto insrt = mInflightFetches.insert(syntax_id);
if (!insrt.second)
{
- LL_WARNS("SyntaxLSL") << "Already downloading keyword file called \"" << fileSpec << "\"." << LL_ENDL;
+ LL_WARNS("SyntaxLSL") << "Already downloading keyword file for syntax ID \"" << syntax_id << "\"." << LL_ENDL;
return;
}
@@ -136,11 +199,11 @@ void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- mInflightFetches.erase(fileSpec);
+ mInflightFetches.erase(syntax_id);
if (!status)
{
- LL_WARNS("SyntaxLSL") << "Failed to fetch syntax file \"" << fileSpec << "\"" << LL_ENDL;
+ LL_WARNS("SyntaxLSL") << "Failed to fetch syntax file for syntax ID \"" << syntax_id << "\"" << LL_ENDL;
return;
}
@@ -148,13 +211,38 @@ void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
if (isSupportedVersion(result))
{
- // Shuttle this task to the main coro/worker.
- // loadKeywordsIntoLLSD will attempt to get a mutex which is not coro aware.
- LLAppViewer::instance()->postToMainCoro([this, result, fileSpec]()
+ std::string path = buildCacheDirectoryName(syntax_id);
+
+ if (!LLFile::exists(path))
+ {
+ LL_DEBUGS("SyntaxLSL") << "Cache directory '" << path << "' does not exist. Attempting to create." << LL_ENDL;
+ if (LLFile::mkdir(path))
{
- setKeywordsXml(result);
- cacheFile(fileSpec, result);
- loadKeywordsIntoLLSD();
+ LL_WARNS("SyntaxLSL") << "Failed to create cache directory '" << path << "'. Cannot cache syntax defs file." << LL_ENDL;
+ return;
+ }
+ }
+
+ // Note that after this call the file cache will have all well known files pointing
+ // to the default versions, so below, where we get the path to the lua keywords
+ // well be loading the default version.
+ buildDefaultCache();
+
+ // The LSL keywords we just received
+ std::string full_path = gDirUtilp->add(path, FILENAME_INTERNAL_LSL);
+ if (writeCacheFile(full_path, result))
+ {
+ mFileCachePaths.addNamePath(FILENAME_INTERNAL_LSL, full_path);
+ }
+ // We need to manually load the Lua keywords
+ full_path = mFileCachePaths.getPath(FILENAME_INTERNAL_LUA);
+ LLSD lua_defs = loadDeserializedCacheFile(full_path);
+
+ setKeywords(result, lua_defs);
+
+ // Shuttle this task to the main coro/worker.
+ LLAppViewer::instance()->postToMainCoro([this]() {
+ mSyntaxIDChangedSignal();
});
}
else
@@ -164,73 +252,198 @@ void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
}
-//-----------------------------------------------------------------------------
-// cacheFile
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::cacheFile(const std::string &fileSpec, const LLSD& content_ref)
+void LLSyntaxDefCache::fetchKeywordsDefsCoro(std::string url, LLUUID syntax_id)
{
- std::stringstream str;
- LLSDSerialize::toXML(content_ref, str);
- const std::string xml = str.str();
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter =
+ std::make_shared("fetchKeywordsDefsCoro", httpPolicy);
+ LLCore::HttpRequest::ptr_t httpRequest = std::make_shared();
- // save the str to disk, usually to the cache.
- llofstream file(fileSpec.c_str(), std::ios_base::out);
- file.write(xml.c_str(), str.str().size());
- file.close();
+ static std::set inflightDefsFetches;
+ auto insrt = inflightDefsFetches.insert(syntax_id);
+ //auto insrt = mInflightFetches.insert(syntax_id);
+ if (!insrt.second)
+ {
+ LL_WARNS("SyntaxLSL") << "Already downloading keyword defs for \"" << syntax_id << "\"." << LL_ENDL;
+ return;
+ }
- LL_DEBUGS("SyntaxLSL") << "Syntax file received, saving as: '" << fileSpec << "'" << LL_ENDL;
-}
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
-//-----------------------------------------------------------------------------
-// initialize
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::initialize()
-{
- if(mInitialized) return;
- if (mSyntaxId.isNull())
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ inflightDefsFetches.erase(syntax_id);
+
+ if (!status)
{
- loadDefaultKeywordsIntoLLSD();
+ LL_WARNS("SyntaxLSL") << "Failed to fetch syntax file \"" << syntax_id << "\"" << LL_ENDL;
+ result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+ return;
}
- else if (!mCapabilityURL.empty())
+
+ // Now we need to walk through the returned LLSD. It consists of a map keyed on the file name containing a binary
+ // blob of the actual file contents.
+ LLSD files = result["files"];
+ LLSD memcached_keywords;
+ if (files.isMap())
{
- LL_DEBUGS("SyntaxLSL") << "LSL version has changed, getting appropriate file." << LL_ENDL;
+ std::string path = buildCacheDirectoryName(syntax_id);
- // Need a full spec regardless of file source, so build it now.
- buildFullFileSpec();
- if (mSyntaxId.notNull())
+ if (!LLFile::exists(path))
{
- if (!gDirUtilp->fileExists(mFullFileSpec))
- { // Does not exist, so fetch it from the capability
- LL_DEBUGS("SyntaxLSL") << "LSL syntax not cached, attempting download." << LL_ENDL;
- fetchKeywordsFile(mFullFileSpec);
- }
- else
+ LL_DEBUGS("SyntaxLSL") << "Cache directory '" << path << "' does not exist. Attempting to create." << LL_ENDL;
+ if (LLFile::mkdir(path))
{
- LL_DEBUGS("SyntaxLSL") << "Found cached Syntax file: " << mFullFileSpec << " Loading keywords." << LL_ENDL;
- loadKeywordsIntoLLSD();
+ LL_WARNS("SyntaxLSL") << "Failed to create cache directory '" << path << "'. Cannot cache syntax defs file." << LL_ENDL;
+ return;
}
}
- else
+
+ buildDefaultCache();
+
+ for (const auto &[filename, contents] : llsd::inMap(files))
{
- LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId is null. Loading default values" << LL_ENDL;
- loadDefaultKeywordsIntoLLSD();
+ std::string full_path = gDirUtilp->add(path, filename);
+
+ if (MEMCACHED_LLSD.find(filename) != MEMCACHED_LLSD.end())
+ { // Maintain some keyword LLSDs internally, LSL and Lua
+ memcached_keywords[filename] = contents;
+ }
+
+ if (writeCacheFile(full_path, contents))
+ {
+ mFileCachePaths.addNamePath(filename, full_path);
+ }
}
}
else
{
- LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId capability URL is empty." << LL_ENDL;
- loadDefaultKeywordsIntoLLSD();
+ LL_WARNS("SyntaxLSL") << "Malformed syntax defs response, missing 'files' map." << LL_ENDL;
+ }
+
+ result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+
+ setKeywords(memcached_keywords[FILENAME_INTERNAL_LSL], memcached_keywords[FILENAME_INTERNAL_LUA]);
+ LLAppViewer::instance()->postToMainCoro(
+ [this]()
+ {
+ mSyntaxIDChangedSignal();
+ });
+}
+
+//-----------------------------------------------------------------------------
+// buildCache
+// Constructs the cache file paths for the given syntax ID. If the syntax ID is null,
+// constructs the default cache file paths.
+void LLSyntaxDefCache::buildCachePaths(const LLUUID &syntax_id)
+{
+ if (syntax_id.notNull())
+ { // Initialize the cache files to point to the default files
+ buildCachePaths(LLUUID::null);
+ }
+ else
+ {
+ mFileCachePaths.clear();
+ }
+
+ std::string cache_dir = buildCacheDirectoryName(syntax_id);
+ if (!LLFile::exists(cache_dir))
+ {
+ LL_DEBUGS("SyntaxLSL") << "Cache directory '" << cache_dir << "' does not exist." << LL_ENDL;
+ return;
+ }
+
+ auto files = gDirUtilp->getFilesInDir(cache_dir);
+ for (const auto &file : files)
+ {
+ mFileCachePaths.addNamePath(file, gDirUtilp->add(cache_dir, file));
+ }
+}
+
+bool LLSyntaxDefCache::writeCacheFile(const std::string &fileSpec, const LLSD& content_ref)
+{
+ bool binary(content_ref.isBinary());
+ std::ios_base::openmode mode(binary ? (std::ios_base::out | std::ios_base::binary)
+ : std::ios_base::out);
+ std::ofstream file(fileSpec.c_str(), mode);
+
+ if (!file.is_open())
+ {
+ LL_WARNS("SyntaxLSL") << "Failed to open file for writing: '" << fileSpec << "'" << LL_ENDL;
+ return false;
+ }
+
+ if (binary)
+ {
+ LL_DEBUGS("SyntaxLSL") << "Caching raw content to '" << fileSpec << "'" << LL_ENDL;
+ file.write((const char*)content_ref.asBinary().data(), content_ref.asBinary().size());
+ }
+ else
+ {
+ LL_DEBUGS("SyntaxLSL") << "Caching XML content to '" << fileSpec << "'" << LL_ENDL;
+ LLSDSerialize::serialize(content_ref, file, LLSDSerialize::LLSD_XML, LLSDFormatter::OPTIONS_PRETTY);
+ }
+ file.close();
+
+ if (!file.good())
+ {
+ LL_WARNS("SyntaxLSL") << "Failed to write content to file: '" << fileSpec << "'" << LL_ENDL;
+ return false;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// checkCacheAndLoad
+// Tests the local cache for the given syntax ID. If found it loads the keywords
+// from the cache into LLSD and returns true. Otherwise returns false.
+bool LLSyntaxDefCache::checkCacheAndLoad(const LLUUID& syntax_id)
+{
+ if (checkLocalCache(syntax_id))
+ {
+ buildCachePaths(syntax_id);
+ loadKeywordsIntoLLSD();
+ return true;
+ }
+ return false;
+}
+
+std::string LLSyntaxDefCache::buildCacheDirectoryName(const LLUUID& syntax_id)
+{
+ if (syntax_id.isNull())
+ {
+ LL_DEBUGS("SyntaxLSL") << "No SyntaxID, using app settings directory." << LL_ENDL;
+ return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "syntax_default");
+ }
+ else
+ {
+ LL_DEBUGS("SyntaxLSL") << "Using cache directory for SyntaxID '" << syntax_id << "'." << LL_ENDL;
+ std::string cache_dir_name = "syntax_" + syntax_id.asString();
+
+ return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
+ }
+}
+
+bool LLSyntaxDefCache::checkLocalCache(const LLUUID& syntax_id) const
+{
+ if (syntax_id.isNull())
+ { // Cache check will always fail if we don't have a valid SyntaxID, so skip it in that case.
+ LL_DEBUGS("SyntaxLSL") << "No SyntaxID, skipping local cache check." << LL_ENDL;
+ return false;
}
- mInitialized = true;
+
+ // Check for the existence of the cache directory for this syntax ID. If it doesn't exist, then we don't have a cached file.
+ std::string cache_dir = buildCacheDirectoryName(syntax_id);
+ return gDirUtilp->fileExists(cache_dir);
}
+
//-----------------------------------------------------------------------------
// isSupportedVersion
//-----------------------------------------------------------------------------
-const U32 LLSD_SYNTAX_LSL_VERSION_EXPECTED = 2;
-const std::string LLSD_SYNTAX_LSL_VERSION_KEY("llsd-lsl-syntax-version");
-bool LLSyntaxIdLSL::isSupportedVersion(const LLSD& content)
+bool LLSyntaxDefCache::isSupportedVersion(const LLSD& content)
{
bool is_valid = false;
/*
@@ -256,128 +469,100 @@ bool LLSyntaxIdLSL::isSupportedVersion(const LLSD& content)
}
//-----------------------------------------------------------------------------
-// loadDefaultKeywordsIntoLLSD()
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::loadDefaultKeywordsIntoLLSD()
-{
- mSyntaxId.setNull();
- buildFullFileSpec();
- loadKeywordsIntoLLSD();
-}
-
-//-----------------------------------------------------------------------------
-// loadKeywordsFileIntoLLSD
+// loadKeywordsIntoLLSD
//-----------------------------------------------------------------------------
/**
* @brief Load xml serialized LLSD
- * @desc Opens the specified filespec and attempts to deserializes the
- * contained data to the specified LLSD object. indicate success/failure with
- * sLoaded/sLoadFailed members.
+ * @desc Open the internal lsl keywords files and deserialize them into the correct
+ * members.
*/
-void LLSyntaxIdLSL::loadKeywordsIntoLLSD()
+void LLSyntaxDefCache::loadKeywordsIntoLLSD()
{
- LLSD content;
- llifstream file;
- file.open(mFullFileSpec.c_str());
- if (file.is_open())
+ for (auto& filename : MEMCACHED_LLSD)
{
- if (LLSDSerialize::fromXML(content, file) != LLSDParser::PARSE_FAILURE)
+ // Note, in the case of the legacy language cap (it only delivers the LSL keywords file)
+ // The mFileCachePaths will have been initialized in such a way that the Lua keywords
+ // point to the default file.
+ std::string full_path = mFileCachePaths.getPath(filename);
+ if (!full_path.empty())
{
- if (isSupportedVersion(content))
+ LLSD content = loadDeserializedCacheFile(full_path);
+ if (!content.isUndefined() && isSupportedVersion(content))
{
- LL_DEBUGS("SyntaxLSL") << "Deserialized: " << mFullFileSpec << LL_ENDL;
+ LL_DEBUGS("SyntaxLSL") << "Deserialized cached file: " << full_path << LL_ENDL;
+ if (filename == FILENAME_INTERNAL_LSL)
+ {
+ mLSLKeywords = content;
+ }
+ else if (filename == FILENAME_INTERNAL_LUA)
+ {
+ mLuaKeywords = content;
+ }
}
else
{
- LL_WARNS("SyntaxLSL") << "Unknown or unsupported version of syntax file." << LL_ENDL;
+ LL_WARNS("SyntaxLSL") << "Unknown or unsupported version of syntax file " << full_path << "." << LL_ENDL;
}
}
}
- else
- {
- LL_WARNS("SyntaxLSL") << "Failed to open: " << mFullFileSpec << LL_ENDL;
- }
- mKeywordsXml = content;
- mSyntaxIDChangedSignal();
-}
-bool LLSyntaxIdLSL::keywordFetchInProgress()
-{
- return !mInflightFetches.empty();
+ mSyntaxIDChangedSignal();
}
-void LLSyntaxIdLSL::handleRegionChanged()
+std::vector LLSyntaxDefCache::getCacheFileNames() const
{
- if (syntaxIdChanged())
+ std::vector names;
+ for (const auto& [name, path] : mFileCachePaths)
{
- buildFullFileSpec();
- fetchKeywordsFile(mFullFileSpec);
- mInitialized = false;
+ names.push_back(name);
}
+ return names;
}
-void LLSyntaxIdLSL::handleCapsReceived(const LLUUID& region_uuid)
+LLSD LLSyntaxDefCache::loadDeserializedCacheFile(const std::string& file_path)
{
- LLViewerRegion* current_region = gAgent.getRegion();
-
- if (region_uuid.notNull()
- && current_region->getRegionID() == region_uuid)
+ std::ifstream file(file_path.c_str());
+ if (file.good())
{
- syntaxIdChanged();
+ LLSD content;
+ if (LLSDSerialize::deserialize(content, file, -1))
+ {
+ return content;
+ }
}
+ else
+ {
+ LL_WARNS("SyntaxLSL") << "Failed to open cached file: " << file_path << LL_ENDL;
+ }
+ return LLSD();
}
-boost::signals2::connection LLSyntaxIdLSL::addSyntaxIDCallback(const syntax_id_changed_signal_t::slot_type& cb)
-{
- return mSyntaxIDChangedSignal.connect(cb);
-}
-
-
-
-//-----------------------------------------------------------------------------
-// LLSyntaxLua
-//-----------------------------------------------------------------------------
-LLSyntaxLua::LLSyntaxLua()
- : mKeywordsXml(LLSD())
- , mInitialized(false)
-{
-}
-
-void LLSyntaxLua::initialize()
-{
- if (mInitialized) return;
-
- loadDefaultKeywordsIntoLLSD();
- loadLuaTypesIntoLLSD();
- mInitialized = true;
-}
-
-void LLSyntaxLua::loadDefaultKeywordsIntoLLSD()
+std::string LLSyntaxDefCache::loadCacheFile(const std::string& name) const
{
- std::string fullFileSpec = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, FILENAME_DEFAULT_LUA);
- llifstream file(fullFileSpec.c_str());
-
- if (file.good())
+ std::string full_path = mFileCachePaths.getPath(name);
+ if (!full_path.empty())
{
- LLSD content;
- if (LLSDSerialize::fromXML(content, file) != LLSDParser::PARSE_FAILURE)
+ std::ifstream file(full_path.c_str());
+ if (file.good())
+ {
+ std::ostringstream ss;
+ ss << file.rdbuf();
+ return (file.good()) ? ss.str() : std::string();
+ }
+ else
{
- mKeywordsXml = content;
+ LL_WARNS("SyntaxLSL") << "Failed to open cached file: " << full_path << LL_ENDL;
}
}
+ return std::string();
}
-void LLSyntaxLua::loadLuaTypesIntoLLSD()
+LLSD LLSyntaxDefCache::loadCacheFileAsLLSD(const std::string& name) const
{
- std::string fullFileSpec = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "types_lua_default.xml");
- llifstream file(fullFileSpec.c_str());
-
- if (file.good())
+ std::string full_path = mFileCachePaths.getPath(name);
+ if (!full_path.empty())
{
- LLSD content;
- if (LLSDSerialize::fromXML(content, file) != LLSDParser::PARSE_FAILURE)
- {
- mTypesXml = content;
- }
+ return loadDeserializedCacheFile(full_path);
}
+ return LLSD();
}
diff --git a/indra/newview/llsyntaxid.h b/indra/newview/llsyntaxid.h
index 51103e3396..acf8020d58 100644
--- a/indra/newview/llsyntaxid.h
+++ b/indra/newview/llsyntaxid.h
@@ -25,8 +25,7 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-#ifndef LL_SYNTAXID_H
-#define LL_SYNTAXID_H
+#pragma once
#include "llviewerprecompiledheaders.h"
@@ -34,66 +33,117 @@
#include "lleventcoro.h"
#include "llcoros.h"
-class fetchKeywordsFileResponder;
-
-class LLSyntaxIdLSL : public LLSingleton
+class LLSyntaxDefCache : public LLSingleton
{
- LLSINGLETON(LLSyntaxIdLSL);
- friend class fetchKeywordsFileResponder;
+ LLSINGLETON(LLSyntaxDefCache) = default;
public:
using syntax_id_changed_signal_t = boost::signals2::signal;
using syntax_id_changed_h = boost::signals2::connection;
-
- void initialize();
- bool keywordFetchInProgress();
- LLSD getKeywordsXML() const { return mKeywordsXml; };
+ class cache_names_t
+ {
+ public:
+ using name_path_map_t = std::unordered_map;
+ using iterator = name_path_map_t::iterator;
+ using const_iterator = name_path_map_t::const_iterator;
+
+ cache_names_t() = default;
+ ~cache_names_t() = default;
+
+ std::string getPath(const std::string &name) const
+ {
+ auto it = mNamePathMap.find(name);
+ if (it != mNamePathMap.end())
+ {
+ return it->second;
+ }
+ return std::string();
+ }
+
+ bool hasName(const std::string &name) const
+ {
+ return mNamePathMap.find(name) != mNamePathMap.end();
+ }
+
+ void addNamePath(const std::string &name, const std::string &path)
+ {
+ mNamePathMap[name] = path;
+ }
+
+ iterator begin() { return mNamePathMap.begin(); }
+ const_iterator begin() const { return mNamePathMap.begin(); }
+ iterator end() { return mNamePathMap.end(); }
+ const_iterator end() const { return mNamePathMap.end(); }
+
+ size_t size() const { return mNamePathMap.size(); }
+ void clear() { mNamePathMap.clear(); }
+ bool empty() const { return mNamePathMap.empty(); }
+
+ iterator find(const std::string &name) { return mNamePathMap.find(name); }
+ const_iterator find(const std::string &name) const { return mNamePathMap.find(name); }
+
+ private:
+ name_path_map_t mNamePathMap;
+ };
+
+ bool keywordFetchInProgress() const { return !mInflightFetches.empty(); }
+ LLSD getLSLKeywords() const { return mLSLKeywords; };
+ LLSD getLuaKeywords() const { return mLuaKeywords; };
LLUUID getSyntaxID() const { return mSyntaxId; }
syntax_id_changed_h addSyntaxIDCallback(const syntax_id_changed_signal_t::slot_type& cb);
-private:
- std::set mInflightFetches;
- syntax_id_changed_signal_t mSyntaxIDChangedSignal;
- syntax_id_changed_h mRegionChangedCallback;
-
- bool syntaxIdChanged();
- bool isSupportedVersion(const LLSD& content);
- void handleRegionChanged();
- void handleCapsReceived(const LLUUID& region_uuid);
- void setKeywordsXml(const LLSD& content) { mKeywordsXml = content; };
- void buildFullFileSpec();
- void fetchKeywordsFile(const std::string& filespec);
- void loadDefaultKeywordsIntoLLSD();
- void loadKeywordsIntoLLSD();
-
- void fetchKeywordsFileCoro(std::string url, std::string fileSpec);
- void cacheFile(const std::string &fileSpec, const LLSD& content_ref);
-
- std::string mCapabilityURL;
- std::string mFullFileSpec;
- ELLPath mFilePath;
- LLUUID mSyntaxId;
- LLSD mKeywordsXml;
- bool mInitialized;
+ bool checkCacheAndLoad(const LLUUID& syntax_id);
-};
+ static std::string buildCacheDirectoryName(const LLUUID& syntax_id);
+ using const_iterator = cache_names_t::const_iterator;
-class LLSyntaxLua : public LLSingleton
-{
- LLSINGLETON(LLSyntaxLua);
+ const_iterator begin() const { return mFileCachePaths.begin(); }
+ const_iterator end() const { return mFileCachePaths.end(); }
-public:
- void initialize();
- LLSD getKeywordsXML() const { return mKeywordsXml; }
- LLSD getTypesXML() const { return mTypesXml; }
+ size_t size() const { return mFileCachePaths.size(); }
+ bool empty() const { return mFileCachePaths.empty(); }
+
+ const_iterator find(const std::string& name) const { return mFileCachePaths.find(name); }
+
+ std::vector getCacheFileNames() const;
+ bool hasCacheFile(const std::string& name) const { return mFileCachePaths.hasName(name); }
+ std::string loadCacheFile(const std::string& name) const;
+ LLSD loadCacheFileAsLLSD(const std::string& name) const;
+
+protected:
+ void initSingleton() override;
+ void cleanupSingleton() override;
private:
- void loadDefaultKeywordsIntoLLSD();
- void loadLuaTypesIntoLLSD();
- LLSD mKeywordsXml;
- LLSD mTypesXml;
- bool mInitialized;
-};
-#endif // LLSYNTAXID_H
+ bool updateSyntaxId();
+ static bool isSupportedVersion(const LLSD& content);
+ void handleRegionChanged();
+ void handleCapsReceived(const LLUUID& region_uuid);
+ void setKeywords(const LLSD& lsl, const LLSD& lua) { mLSLKeywords = lsl; mLuaKeywords = lua; };
+
+ void loadKeywordsIntoLLSD();
+
+ void fetchKeywords();
+ void fetchKeywordsFileCoro(std::string url, LLUUID syntax_id);
+ void fetchKeywordsDefsCoro(std::string url, LLUUID syntax_id);
+
+ bool checkLocalCache(const LLUUID& syntax_id) const;
+ void buildDefaultCache() { buildCachePaths(LLUUID::null); }
+ void buildCachePaths(const LLUUID &syntax_id);
+ bool writeCacheFile(const std::string &fileSpec, const LLSD& content_ref);
+
+ static LLSD loadDeserializedCacheFile(const std::string& file_path);
+
+ std::set mInflightFetches;
+ syntax_id_changed_signal_t mSyntaxIDChangedSignal;
+ syntax_id_changed_h mRegionChangedCallback;
+
+ std::string mCapabilityURL;
+ cache_names_t mFileCachePaths;
+ LLUUID mSyntaxId;
+ LLSD mLSLKeywords;
+ LLSD mLuaKeywords;
+ bool mUseDefsCap{ false };
+};
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 42a587f376..eed118e7d0 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -3291,6 +3291,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("RequestTextureDownload");
capabilityNames.append("ResourceCostSelected");
capabilityNames.append("RetrieveNavMeshSrc");
+ capabilityNames.append("ScriptDefinitions");
capabilityNames.append("SearchStatRequest");
capabilityNames.append("SearchStatTracking");
capabilityNames.append("SendPostcard");
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 21e50f4dcb..524077f1b2 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -64,6 +64,16 @@ def construct(self):
super(ViewerManifest, self).construct()
self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg")
+ # ... and the lsl/lua script definition files (needed at build time and packaging)
+ pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
+ with self.prefix(src=os.path.join(pkgdir, 'lsl_definitions'), dst="app_settings/syntax_default"):
+ self.path("*.txt")
+ self.path("*.yaml")
+ self.path("*.xml")
+ self.path("*.json")
+ self.path("*.luau")
+ self.path("*.yml")
+
if self.is_packaging_viewer():
with self.prefix(src_dst="app_settings"):
self.exclude("logcontrol.xml")
@@ -92,7 +102,7 @@ def construct(self):
with self.prefix(src=pkgdir):
self.path("dictionaries")
- # include the extracted packages information (see BuildPackagesInfo.cmake)
+ # include the extracted packages information
self.path(src=os.path.join(self.args['build'],"packages-info.txt"), dst="packages-info.txt")
# CHOP-955: If we have "sourceid" or "viewer_channel" in the
# build process environment, generate it into