Advanced Scripting Techniques

Resource Management

Efficiently handle external resources in your userscripts:

// Declare resources in the editor's Resources section:
// Name: jquery, URL: https://code.jquery.com/jquery-3.6.0.min.js
// Name: styles, URL: https://example.com/custom.css

// Use resources in your script
const jqueryCode = GM_getResourceText('jquery');
const customCSS = GM_getResourceText('styles');

// Inject jQuery if not already present
if (typeof $ === 'undefined') {
    eval(jqueryCode);
}

// Apply custom styles
GM_addStyle(customCSS);

Cross-Origin Requests

Make secure cross-origin requests with GM_xmlhttpRequest:

// Advanced request with timeout and retry logic
function makeRequest(url, retries = 3) {
    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            method: 'GET',
            url: url,
            timeout: 10000,
            headers: {
                'User-Agent': 'CodeTweak UserScript',
                'Accept': 'application/json'
            },
            onload: (response) => {
                if (response.status === 200) {
                    resolve(JSON.parse(response.responseText));
                } else if (retries > 0) {
                    setTimeout(() => {
                        makeRequest(url, retries - 1)
                            .then(resolve)
                            .catch(reject);
                    }, 1000);
                } else {
                    reject(new Error(`HTTP ${response.status}`));
                }
            },
            onerror: () => {
                if (retries > 0) {
                    setTimeout(() => {
                        makeRequest(url, retries - 1)
                            .then(resolve)
                            .catch(reject);
                    }, 1000);
                } else {
                    reject(new Error('Network error'));
                }
            }
        });
    });
}

Debugging & Development

Debug Mode

Enable comprehensive debugging for development:

// Add debug logging to your scripts
const DEBUG = GM_getValue('debug_mode', false);

function debugLog(...args) {
    if (DEBUG) {
        console.log('[UserScript Debug]', ...args);
    }
}

// Use throughout your script
debugLog('Script initialized');
debugLog('Processing element:', element);
debugLog('API response:', data);

Error Handling

Implement robust error handling in your userscripts:

// Wrap your main script logic
(function() {
    'use strict';
    
    try {
        // Your script code here
        initializeScript();
    } catch (error) {
        console.error('UserScript Error:', error);
        
        // Optional: Report errors
        GM_setValue('last_error', {
            message: error.message,
            stack: error.stack,
            timestamp: Date.now()
        });
        
        // Optional: Show user notification
        if (typeof GM_notification !== 'undefined') {
            GM_notification({
                text: 'Script encountered an error. Check console for details.',
                title: 'UserScript Error'
            });
        }
    }
})();

Performance Monitoring

Monitor your script's performance impact:

// Performance monitoring wrapper
function measurePerformance(name, fn) {
    const start = performance.now();
    const result = fn();
    const end = performance.now();
    
    const duration = end - start;
    console.log(`${name} took ${duration.toFixed(2)}ms`);
    
    // Store performance data
    const perfData = GM_getValue('performance_data', {});
    perfData[name] = (perfData[name] || []).concat(duration).slice(-10);
    GM_setValue('performance_data', perfData);
    
    return result;
}

// Usage
measurePerformance('DOM Processing', () => {
    document.querySelectorAll('.target').forEach(processElement);
});

Security Considerations

Input Validation

Always validate data from external sources:

// Validate stored data
function getSafeValue(key, defaultValue, validator) {
    const value = GM_getValue(key, defaultValue);
    
    if (typeof validator === 'function' && !validator(value)) {
        console.warn(`Invalid stored value for ${key}, using default`);
        return defaultValue;
    }
    
    return value;
}

// Usage
const userSettings = getSafeValue('settings', {}, (val) => {
    return typeof val === 'object' && val !== null;
});

const maxRetries = getSafeValue('max_retries', 3, (val) => {
    return typeof val === 'number' && val >= 0 && val <= 10;
});

Secure Communication

Best practices for external API communication:

Troubleshooting

Common Issues & Solutions

Scripts Not Executing

Symptoms: Scripts appear enabled but don't run on target pages.

Performance Issues

Symptoms: Pages load slowly or browser becomes unresponsive.

Storage Problems

Symptoms: GM_getValue returns unexpected values or data is lost.

Diagnostic Tools

Built-in tools for troubleshooting:

// Check CodeTweak status
console.log('CodeTweak version:', chrome.runtime.getManifest().version);

// List all stored values
console.log('Stored keys:', GM_listValues());

// Check enabled APIs
console.log('Available APIs:', Object.keys(window).filter(k => k.startsWith('GM_')));

// Monitor performance
const observer = new PerformanceObserver((list) => {
    list.getEntries().forEach((entry) => {
        if (entry.duration > 100) {
            console.warn('Slow operation detected:', entry.name, entry.duration + 'ms');
        }
    });
});
observer.observe({entryTypes: ['measure']});